<commit_before>//===- TypeTraitsTest.cpp -------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/type_traits.h"

namespace {

// Compile-time tests using static assert.
namespace triviality {

// Helper for compile time checking trivially copy constructible and trivially
// move constructible type traits.
template <typename T, bool IsTriviallyCopyConstructible,
          bool IsTriviallyMoveConstructible>
void TrivialityTester() {
  static_assert(llvm::is_trivially_copy_constructible<T>::value ==
                    IsTriviallyCopyConstructible,
                "Mismatch in expected trivial copy construction!");
  static_assert(llvm::is_trivially_move_constructible<T>::value ==
                    IsTriviallyMoveConstructible,
                "Mismatch in expected trivial move construction!");

#if __clang__ || _MSC_VER || __GNUC__ > 5
  // On compilers with support for the standard traits, make sure they agree.
  static_assert(std::is_trivially_copy_constructible<T>::value ==
                    IsTriviallyCopyConstructible,
                "Mismatch in expected trivial copy construction!");
  static_assert(std::is_trivially_move_constructible<T>::value ==
                    IsTriviallyMoveConstructible,
                "Mismatch in expected trivial move construction!");
#endif
};

template void TrivialityTester<int, true, true>();
template void TrivialityTester<void *, true, true>();
template void TrivialityTester<int &, true, true>();
template void TrivialityTester<int &&, false, true>();

struct X {};
struct Y {
  Y(const Y &);
};
struct Z {
  Z(const Z &);
  Z(Z &&);
};
struct A {
  A(const A &) = default;
  A(A &&);
};
struct B {
  B(const B &);
  B(B &&) = default;
};

template void TrivialityTester<X, true, true>();
template void TrivialityTester<Y, false, false>();
template void TrivialityTester<Z, false, false>();
template void TrivialityTester<A, true, false>();
template void TrivialityTester<B, false, true>();

template void TrivialityTester<Z &, true, true>();
template void TrivialityTester<A &, true, true>();
template void TrivialityTester<B &, true, true>();
template void TrivialityTester<Z &&, false, true>();
template void TrivialityTester<A &&, false, true>();
template void TrivialityTester<B &&, false, true>();

} // namespace triviality

} // end anonymous namespace
<commit_msg>[Support] This sanity check in the test only works with certain versions of libstdc++, not just certain versions of GCC. The original macros broke when using Clang + libstdc++4.9 sadly.<commit_after>//===- TypeTraitsTest.cpp -------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/type_traits.h"

namespace {

// Compile-time tests using static assert.
namespace triviality {

// Helper for compile time checking trivially copy constructible and trivially
// move constructible type traits.
template <typename T, bool IsTriviallyCopyConstructible,
          bool IsTriviallyMoveConstructible>
void TrivialityTester() {
  static_assert(llvm::is_trivially_copy_constructible<T>::value ==
                    IsTriviallyCopyConstructible,
                "Mismatch in expected trivial copy construction!");
  static_assert(llvm::is_trivially_move_constructible<T>::value ==
                    IsTriviallyMoveConstructible,
                "Mismatch in expected trivial move construction!");

#if defined(_LIBCPP_VERSION) || defined(_MSC_VER)
  // On compilers with support for the standard traits, make sure they agree.
  static_assert(std::is_trivially_copy_constructible<T>::value ==
                    IsTriviallyCopyConstructible,
                "Mismatch in expected trivial copy construction!");
  static_assert(std::is_trivially_move_constructible<T>::value ==
                    IsTriviallyMoveConstructible,
                "Mismatch in expected trivial move construction!");
#endif
};

template void TrivialityTester<int, true, true>();
template void TrivialityTester<void *, true, true>();
template void TrivialityTester<int &, true, true>();
template void TrivialityTester<int &&, false, true>();

struct X {};
struct Y {
  Y(const Y &);
};
struct Z {
  Z(const Z &);
  Z(Z &&);
};
struct A {
  A(const A &) = default;
  A(A &&);
};
struct B {
  B(const B &);
  B(B &&) = default;
};

template void TrivialityTester<X, true, true>();
template void TrivialityTester<Y, false, false>();
template void TrivialityTester<Z, false, false>();
template void TrivialityTester<A, true, false>();
template void TrivialityTester<B, false, true>();

template void TrivialityTester<Z &, true, true>();
template void TrivialityTester<A &, true, true>();
template void TrivialityTester<B &, true, true>();
template void TrivialityTester<Z &&, false, true>();
template void TrivialityTester<A &&, false, true>();
template void TrivialityTester<B &&, false, true>();

} // namespace triviality

} // end anonymous namespace
<|endoftext|>


<commit_before>#include <algorithm>
#include <chrono>
#include <cmath>
#include <iostream>
#include <string>
#include <sys/time.h>
#include <thread>

#include <rclcpp/rclcpp.hpp>

#include <simple_msgs/AllBuiltinTypes.h>
#include <simple_msgs/AllDynamicArrayTypes.h>
#include <simple_msgs/AllPrimitiveTypes.h>
#include <simple_msgs/AllStaticArrayTypes.h>
#include <simple_msgs/Nested.h>
#include <simple_msgs/String.h>
#include <simple_msgs/Uint32.h>

#include <userland_msgs/AddTwoInts.h>

int main(int argc, char** argv)
{
  rclcpp::init(argc, argv);

  auto node = rclcpp::Node::make_shared("add_two_ints_client");

  auto client = node->create_client<userland_msgs::AddTwoInts>("add_two_ints");
  auto request = std::make_shared<userland_msgs::AddTwoInts::Request>();
  auto response = std::make_shared<userland_msgs::AddTwoInts::Response>();
  request->a = 2;
  request->b = 3;

  auto f = client->async_send_request(request, response);

  std::future_status status;
  do
  {
    rclcpp::spin_some(node);
    status = f.wait_for(std::chrono::milliseconds(100));
  } while(status != std::future_status::ready && rclcpp::ok());

  if(std::future_status::ready == status)
  {
    std::cout << "FUTURE READY" << std::endl;
    std::cout << f.get()->sum << std::endl;
  }

  return 0;
}
<commit_msg>Added example for callback-based client<commit_after>#include <algorithm>
#include <chrono>
#include <cmath>
#include <iostream>
#include <string>
#include <sys/time.h>
#include <thread>

#include <rclcpp/rclcpp.hpp>

#include <simple_msgs/AllBuiltinTypes.h>
#include <simple_msgs/AllDynamicArrayTypes.h>
#include <simple_msgs/AllPrimitiveTypes.h>
#include <simple_msgs/AllStaticArrayTypes.h>
#include <simple_msgs/Nested.h>
#include <simple_msgs/String.h>
#include <simple_msgs/Uint32.h>

#include <userland_msgs/AddTwoInts.h>

int main(int argc, char** argv)
{
  rclcpp::init(argc, argv);

  auto node = rclcpp::Node::make_shared("add_two_ints_client");

  auto client = node->create_client<userland_msgs::AddTwoInts>("add_two_ints");
  auto request = std::make_shared<userland_msgs::AddTwoInts::Request>();
  auto response = std::make_shared<userland_msgs::AddTwoInts::Response>();
  request->a = 2;
  request->b = 3;

  auto f = client->async_send_request(request, response);

  std::future_status status;
  do
  {
    rclcpp::spin_some(node);
    status = f.wait_for(std::chrono::milliseconds(100));
  } while(status != std::future_status::ready && rclcpp::ok());

  if(std::future_status::ready == status)
  {
    std::cout << "FUTURE READY" << std::endl;
    std::cout << f.get()->sum << std::endl;
  }

  client->async_send_request(
    request, response,
    [] (rclcpp::client::Client<userland_msgs::AddTwoInts>::SharedFuture f) {
      std::cout << "CALLBACK" << std::endl;
  });
  rclcpp::spin(node);

  return 0;
}
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 */

#include "cvmfs_config.h"
#include "swissknife_lsrepo.h"

#include "logging.h"

namespace swissknife {

CommandListCatalogs::CommandListCatalogs() :
  print_tree_(false), print_hash_(false), print_size_(false),
  print_entries_(false) {}

ParameterList CommandListCatalogs::GetParams() {
  ParameterList r;
  r.push_back(Parameter::Mandatory(
              'r', "repository URL (absolute local path or remote URL)"));
  r.push_back(Parameter::Optional('n', "fully qualified repository name"));
  r.push_back(Parameter::Optional('k', "repository master key(s)"));
  r.push_back(Parameter::Optional('l', "temporary directory"));
  r.push_back(Parameter::Switch('t', "print tree structure of catalogs"));
  r.push_back(Parameter::Switch('d', "print digest for each catalog"));
  r.push_back(Parameter::Switch('s', "print catalog file sizes"));
  r.push_back(Parameter::Switch('e', "print number of catalog entries"));
  return r;
}

int CommandListCatalogs::Main(const ArgumentList &args) {
  print_tree_    = (args.count('t') > 0);
  print_hash_    = (args.count('d') > 0);
  print_size_    = (args.count('s') > 0);
  print_entries_ = (args.count('e') > 0);

  const std::string &repo_url  = *args.find('r')->second;
  const std::string &repo_name =
    (args.count('n') > 0) ? *args.find('n')->second : "";
  const std::string &repo_keys =
    (args.count('k') > 0) ? *args.find('k')->second : "";
  const std::string &tmp_dir   =
    (args.count('l') > 0) ? *args.find('l')->second : "/tmp";

  bool success = false;
  if (IsHttpUrl(repo_url)) {
    download::DownloadManager   download_manager;
    signature::SignatureManager signature_manager;
    download_manager.Init(1, true, g_statistics);
    signature_manager.Init();
    if (!signature_manager.LoadPublicRsaKeys(repo_keys)) {
      LogCvmfs(kLogCatalog, kLogStderr, "Failed to load public key(s)");
      return 1;
    }

    HttpObjectFetcher<catalog::Catalog,
                      history::SqliteHistory> fetcher(repo_name,
                                                      repo_url,
                                                      tmp_dir,
                                                      &download_manager,
                                                      &signature_manager);
    success = Run(&fetcher);

    download_manager.Fini();
    signature_manager.Fini();
  } else {
    LocalObjectFetcher<> fetcher(repo_url, tmp_dir);
    success = Run(&fetcher);
  }

  return (success) ? 0 : 1;
}

void CommandListCatalogs::CatalogCallback(
                           const CatalogTraversalData<catalog::Catalog> &data) {
  std::string tree_indent;
  std::string hash_string;
  std::string clg_size;
  std::string clg_entries;
  std::string path;

  if (print_tree_) {
    for (unsigned int i = 1; i < data.tree_level; ++i) {
      tree_indent += "\u2502  ";
    }

    if (data.tree_level > 0)
      tree_indent += "\u251C\u2500 ";
  }

  if (print_hash_) {
    hash_string = data.catalog_hash.ToString() + " ";
  }

  if (print_size_) {
    clg_size = StringifyInt(data.file_size) + "B ";
  }

  if (print_entries_) {
    clg_entries = StringifyInt(data.catalog->GetNumEntries()) + " ";
  }

  path = data.catalog->path().ToString();
  if (path.empty())
    path = "/";

  LogCvmfs(kLogCatalog, kLogStdout, "%s%s%s%s%s",
    tree_indent.c_str(), hash_string.c_str(), clg_size.c_str(),
    clg_entries.c_str(), path.c_str());
}

}  // namespace swissknife
<commit_msg>Refactor: use centralised manifest fetching in lsrepo<commit_after>/**
 * This file is part of the CernVM File System.
 */

#include "cvmfs_config.h"
#include "swissknife_lsrepo.h"

#include "logging.h"

namespace swissknife {

CommandListCatalogs::CommandListCatalogs() :
  print_tree_(false), print_hash_(false), print_size_(false),
  print_entries_(false) {}

ParameterList CommandListCatalogs::GetParams() {
  ParameterList r;
  r.push_back(Parameter::Mandatory(
              'r', "repository URL (absolute local path or remote URL)"));
  r.push_back(Parameter::Optional('n', "fully qualified repository name"));
  r.push_back(Parameter::Optional('k', "repository master key(s)"));
  r.push_back(Parameter::Optional('l', "temporary directory"));
  r.push_back(Parameter::Switch('t', "print tree structure of catalogs"));
  r.push_back(Parameter::Switch('d', "print digest for each catalog"));
  r.push_back(Parameter::Switch('s', "print catalog file sizes"));
  r.push_back(Parameter::Switch('e', "print number of catalog entries"));
  return r;
}

int CommandListCatalogs::Main(const ArgumentList &args) {
  print_tree_    = (args.count('t') > 0);
  print_hash_    = (args.count('d') > 0);
  print_size_    = (args.count('s') > 0);
  print_entries_ = (args.count('e') > 0);

  const std::string &repo_url  = *args.find('r')->second;
  const std::string &repo_name =
    (args.count('n') > 0) ? *args.find('n')->second : "";
  const std::string &repo_keys =
    (args.count('k') > 0) ? *args.find('k')->second : "";
  const std::string &tmp_dir   =
    (args.count('l') > 0) ? *args.find('l')->second : "/tmp";

  bool success = false;
  if (IsHttpUrl(repo_url)) {
    const bool follow_redirects = false;
    if (!this->InitDownloadManager(follow_redirects) ||
        !this->InitSignatureManager(repo_keys)) {
      LogCvmfs(kLogCatalog, kLogStderr, "Failed to init remote connection");
      return 1;
    }

    HttpObjectFetcher<catalog::Catalog,
                      history::SqliteHistory> fetcher(repo_name,
                                                      repo_url,
                                                      tmp_dir,
                                                      download_manager(),
                                                      signature_manager());
    success = Run(&fetcher);
  } else {
    LocalObjectFetcher<> fetcher(repo_url, tmp_dir);
    success = Run(&fetcher);
  }

  return (success) ? 0 : 1;
}

void CommandListCatalogs::CatalogCallback(
                           const CatalogTraversalData<catalog::Catalog> &data) {
  std::string tree_indent;
  std::string hash_string;
  std::string clg_size;
  std::string clg_entries;
  std::string path;

  if (print_tree_) {
    for (unsigned int i = 1; i < data.tree_level; ++i) {
      tree_indent += "\u2502  ";
    }

    if (data.tree_level > 0)
      tree_indent += "\u251C\u2500 ";
  }

  if (print_hash_) {
    hash_string = data.catalog_hash.ToString() + " ";
  }

  if (print_size_) {
    clg_size = StringifyInt(data.file_size) + "B ";
  }

  if (print_entries_) {
    clg_entries = StringifyInt(data.catalog->GetNumEntries()) + " ";
  }

  path = data.catalog->path().ToString();
  if (path.empty())
    path = "/";

  LogCvmfs(kLogCatalog, kLogStdout, "%s%s%s%s%s",
    tree_indent.c_str(), hash_string.c_str(), clg_size.c_str(),
    clg_entries.c_str(), path.c_str());
}

}  // namespace swissknife
<|endoftext|>


<commit_before>#ifndef DIPLOMA_PAGE_ALLOCATOR_HPP
#define DIPLOMA_PAGE_ALLOCATOR_HPP

#include <cstddef>
#include <cstdint>
#include <cassert>

#include <libprecisegc/details/allocators/allocator_tag.hpp>
#include <libprecisegc/details/gc_hooks.hpp>
#include <libprecisegc/details/constants.hpp>
#include <libprecisegc/details/types.hpp>
#include <libprecisegc/details/logging.hpp>

namespace precisegc { namespace details { namespace allocators {

/**
 * page_allocator - allocates memory regions which size is multiple of PAGE_SIZE, aligned by its size
 */
class page_allocator
{
public:
    typedef byte* pointer_type;
    typedef stateless_alloc_tag alloc_tag;

    page_allocator() = default;
    page_allocator(const page_allocator&) = default;
    page_allocator(page_allocator&&) = default;

    byte* allocate(size_t size, size_t alignment = 0)
    {
        assert(size != 0 /*&& size % PAGE_SIZE == 0*/);
        gc_initiation_point(initiation_point_type::HEAP_EXPANSION,
                            initiation_point_data::create_heap_expansion_data(size));
        byte* page = reinterpret_cast<byte*>(aligned_alloc(alignment, size));
        gc_register_page(page, size);
        return page;
    }

    void deallocate(byte* ptr, size_t size, size_t alignment = 0)
    {
        assert(size != 0 && size % PAGE_SIZE == 0);
        gc_deregister_page(ptr, size);
        free(ptr);
    }
};

}}}

#endif //DIPLOMA_PAGE_ALLOCATOR_HPP
<commit_msg>zeroing allocated memory<commit_after>#ifndef DIPLOMA_PAGE_ALLOCATOR_HPP
#define DIPLOMA_PAGE_ALLOCATOR_HPP

#include <cstddef>
#include <cstdint>
#include <cassert>

#include <libprecisegc/details/allocators/allocator_tag.hpp>
#include <libprecisegc/details/gc_hooks.hpp>
#include <libprecisegc/details/constants.hpp>
#include <libprecisegc/details/types.hpp>
#include <libprecisegc/details/logging.hpp>

namespace precisegc { namespace details { namespace allocators {

/**
 * page_allocator - allocates memory regions which size is multiple of PAGE_SIZE, aligned by its size
 */
class page_allocator
{
public:
    typedef byte* pointer_type;
    typedef stateless_alloc_tag alloc_tag;

    page_allocator() = default;
    page_allocator(const page_allocator&) = default;
    page_allocator(page_allocator&&) = default;

    byte* allocate(size_t size, size_t alignment = 0)
    {
        assert(size != 0 /*&& size % PAGE_SIZE == 0*/);
        gc_initiation_point(initiation_point_type::HEAP_EXPANSION,
                            initiation_point_data::create_heap_expansion_data(size));
        byte* page = reinterpret_cast<byte*>(aligned_alloc(alignment, size));
        memset(page, 0, size);
        gc_register_page(page, size);
        return page;
    }

    void deallocate(byte* ptr, size_t size, size_t alignment = 0)
    {
        assert(size != 0 && size % PAGE_SIZE == 0);
        gc_deregister_page(ptr, size);
        free(ptr);
    }
};

}}}

#endif //DIPLOMA_PAGE_ALLOCATOR_HPP
<|endoftext|>


<commit_before>// Copyright (C) 2016 xaizek <xaizek@openmailbox.org>
//
// This file is part of uncov.
//
// uncov is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// uncov 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with uncov.  If not, see <http://www.gnu.org/licenses/>.

#include "FileComparator.hpp"

#include <boost/multi_array.hpp>

#include <cstddef>

#include <deque>
#include <string>
#include <vector>

FileComparator::FileComparator(const std::vector<std::string> &o,
                               const std::vector<int> &oCov,
                               const std::vector<std::string> &n,
                               const std::vector<int> &nCov,
                               bool considerHits)
{
    valid = (o.size() == oCov.size() && n.size() == nCov.size());
    if (!valid) {
        equal = false;
        return;
    }

    boost::multi_array<int, 2> d(boost::extents[o.size() + 1U][n.size() + 1U]);

    // Modified edit distance finding.
    using size_type = std::vector<std::string>::size_type;
    for (size_type i = 0U, nf = o.size(); i <= nf; ++i) {
        for (size_type j = 0U, ns = n.size(); j <= ns; ++j) {
            if (i == 0U) {
                d[i][j] = j;
            } else if (j == 0U) {
                d[i][j] = i;
            } else {
                d[i][j] = std::min(d[i - 1U][j] + 1, d[i][j - 1U] + 1);
                if (o[i - 1U] == n[j - 1U]) {
                    d[i][j] = std::min(d[i - 1U][j - 1U], d[i][j]);
                }
            }
        }
    }

    std::size_t identicalLines = 0;

    auto foldIdentical = [this, &identicalLines](bool last) {
        if (identicalLines > 4) {
            int startContext = last ? 0 : 1;
            int endContext = identicalLines == diffSequence.size() ? 0 : 1;
            int context = startContext + endContext;

            diffSequence.erase(diffSequence.cbegin() + startContext,
                               diffSequence.cbegin() +
                               (identicalLines - endContext));
            diffSequence.emplace(diffSequence.cbegin() + startContext,
                                 DiffLineType::Note,
                                 std::to_string(identicalLines - context) +
                                 " identical lines folded", -1, -1);
        }
        identicalLines = 0;
    };

    auto maybeConsiderIdentical = [&identicalLines, &foldIdentical](int hits) {
        if (hits == -1) {
            ++identicalLines;
        } else {
            foldIdentical(false);
        }
    };

    auto sign = [](int i) {
        if (i < 0) {
            return -1;
        } else if (i == 0) {
            return 0;
        } else {
            return +1;
        }
    };

    // Compose results with folding of long runs of identical lines (longer
    // than two lines).
    int i = o.size(), j = n.size();
    while (i != 0 || j != 0) {
        if (i == 0) {
            maybeConsiderIdentical(nCov[--j]);
            diffSequence.emplace_front(DiffLineType::Added, n[j], -1, j);
        } else if (j == 0) {
            maybeConsiderIdentical(oCov[--i]);
            diffSequence.emplace_front(DiffLineType::Removed, o[i], i, -1);
        } else if (d[i][j] == d[i][j - 1] + 1) {
            maybeConsiderIdentical(nCov[--j]);
            diffSequence.emplace_front(DiffLineType::Added, n[j], -1, j);
        } else if (d[i][j] == d[i - 1][j] + 1) {
            maybeConsiderIdentical(oCov[--i]);
            diffSequence.emplace_front(DiffLineType::Removed, o[i], i, -1);
        } else if (o[--i] == n[--j]) {
            const int oHits = considerHits ? oCov[i] : sign(oCov[i]);
            const int nHits = considerHits ? nCov[j] : sign(nCov[j]);
            if (oHits == nHits) {
                diffSequence.emplace_front(DiffLineType::Identical, o[i], i, j);
                ++identicalLines;
            } else {
                foldIdentical(false);
                diffSequence.emplace_front(DiffLineType::Common, o[i], i, j);
            }
        }
    }

    equal = (identicalLines == diffSequence.size());

    foldIdentical(true);
}

bool
FileComparator::isValidInput() const
{
    return valid;
}

bool
FileComparator::areEqual() const
{
    return equal;
}

const std::deque<DiffLine> &
FileComparator::getDiffSequence() const
{
    return diffSequence;
}
<commit_msg>Don't say that we fold "identical lines"<commit_after>// Copyright (C) 2016 xaizek <xaizek@openmailbox.org>
//
// This file is part of uncov.
//
// uncov is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// uncov 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with uncov.  If not, see <http://www.gnu.org/licenses/>.

#include "FileComparator.hpp"

#include <boost/multi_array.hpp>

#include <cstddef>

#include <deque>
#include <string>
#include <vector>

FileComparator::FileComparator(const std::vector<std::string> &o,
                               const std::vector<int> &oCov,
                               const std::vector<std::string> &n,
                               const std::vector<int> &nCov,
                               bool considerHits)
{
    valid = (o.size() == oCov.size() && n.size() == nCov.size());
    if (!valid) {
        equal = false;
        return;
    }

    boost::multi_array<int, 2> d(boost::extents[o.size() + 1U][n.size() + 1U]);

    // Modified edit distance finding.
    using size_type = std::vector<std::string>::size_type;
    for (size_type i = 0U, nf = o.size(); i <= nf; ++i) {
        for (size_type j = 0U, ns = n.size(); j <= ns; ++j) {
            if (i == 0U) {
                d[i][j] = j;
            } else if (j == 0U) {
                d[i][j] = i;
            } else {
                d[i][j] = std::min(d[i - 1U][j] + 1, d[i][j - 1U] + 1);
                if (o[i - 1U] == n[j - 1U]) {
                    d[i][j] = std::min(d[i - 1U][j - 1U], d[i][j]);
                }
            }
        }
    }

    std::size_t identicalLines = 0;

    auto foldIdentical = [this, &identicalLines](bool last) {
        if (identicalLines > 4) {
            int startContext = last ? 0 : 1;
            int endContext = identicalLines == diffSequence.size() ? 0 : 1;
            int context = startContext + endContext;

            diffSequence.erase(diffSequence.cbegin() + startContext,
                               diffSequence.cbegin() +
                               (identicalLines - endContext));
            diffSequence.emplace(diffSequence.cbegin() + startContext,
                                 DiffLineType::Note,
                                 std::to_string(identicalLines - context) +
                                 " lines folded", -1, -1);
        }
        identicalLines = 0;
    };

    auto maybeConsiderIdentical = [&identicalLines, &foldIdentical](int hits) {
        if (hits == -1) {
            ++identicalLines;
        } else {
            foldIdentical(false);
        }
    };

    auto sign = [](int i) {
        if (i < 0) {
            return -1;
        } else if (i == 0) {
            return 0;
        } else {
            return +1;
        }
    };

    // Compose results with folding of long runs of identical lines (longer
    // than two lines).
    int i = o.size(), j = n.size();
    while (i != 0 || j != 0) {
        if (i == 0) {
            maybeConsiderIdentical(nCov[--j]);
            diffSequence.emplace_front(DiffLineType::Added, n[j], -1, j);
        } else if (j == 0) {
            maybeConsiderIdentical(oCov[--i]);
            diffSequence.emplace_front(DiffLineType::Removed, o[i], i, -1);
        } else if (d[i][j] == d[i][j - 1] + 1) {
            maybeConsiderIdentical(nCov[--j]);
            diffSequence.emplace_front(DiffLineType::Added, n[j], -1, j);
        } else if (d[i][j] == d[i - 1][j] + 1) {
            maybeConsiderIdentical(oCov[--i]);
            diffSequence.emplace_front(DiffLineType::Removed, o[i], i, -1);
        } else if (o[--i] == n[--j]) {
            const int oHits = considerHits ? oCov[i] : sign(oCov[i]);
            const int nHits = considerHits ? nCov[j] : sign(nCov[j]);
            if (oHits == nHits) {
                diffSequence.emplace_front(DiffLineType::Identical, o[i], i, j);
                ++identicalLines;
            } else {
                foldIdentical(false);
                diffSequence.emplace_front(DiffLineType::Common, o[i], i, j);
            }
        }
    }

    equal = (identicalLines == diffSequence.size());

    foldIdentical(true);
}

bool
FileComparator::isValidInput() const
{
    return valid;
}

bool
FileComparator::areEqual() const
{
    return equal;
}

const std::deque<DiffLine> &
FileComparator::getDiffSequence() const
{
    return diffSequence;
}
<|endoftext|>


<commit_before>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// 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 <vector>
#include <iostream>
#include <exception>
#include <iomanip>
#include <ctime>
#include <algorithm>

#include <configuration.hpp>

#include <ArgumentList.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Correlator.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

const unsigned int magicValue = 42;

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, const unsigned int outputSize, cl::Buffer * output_d, std::vector< unsigned int > * baselineMap, cl::Buffer * baselineMap_d);

int main(int argc, char * argv[]) {
  bool reInit = true;
  unsigned int padding = 0;
  unsigned int nrIterations = 0;
  unsigned int clPlatformID = 0;
  unsigned int clDeviceID = 0;
  unsigned int vectorSize = 0;
  unsigned int maxThreads = 0;
  unsigned int maxItems = 0;
  unsigned int nrChannels = 0;
  unsigned int nrStations = 0;
  unsigned int nrSamples = 0;
  isa::OpenCL::KernelConf conf;

  try {
    isa::utils::ArgumentList args(argc, argv);

    clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
    clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
    vectorSize = args.getSwitchArgument< unsigned int >("-vector");
    maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
    maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    nrChannels = args.getSwitchArgument< unsigned int >("-channels");
    nrStations = args.getSwitchArgument< unsigned int >("-stations");
    nrSamples = args.getSwitchArgument< unsigned int >("-samples");
  } catch ( isa::utils::EmptyCommandLine & err ) {
    std::cerr << argv[0] << " -opencl_platform ... -opencl_device ... -padding ... -iterations ... -vector ... -max_threads ... -max_items ... -channels ... -stations ... -samples ..." << std::endl;
    return 1;
  } catch ( std::exception & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  cl::Context clContext;
  std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
  std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
  std::vector< std::vector< cl::CommandQueue > > * clQueues = 0;

  // Allocate host memory
  unsigned int nrBaselines = (nrStations * (nrStations + 1)) / 2;
  std::vector< inputDataType > input(nrChannels * nrStations * nrSamples * nrPolarizations * 2);
  std::vector< inputDataType > output(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2), output_c(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2);
  std::vector< unsigned int > baselineMap(nrBaselines * 2);
  cl::Buffer input_d, output_d, baselineMap_d;

  // Populate data structures
  srand(time(0));
  for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
    for ( unsigned int station = 0; station < nrStations; station++ ) {
      for ( unsigned int sample = 0; sample < nrSamples; sample++ ) {
        for ( unsigned int polarization = 0; polarization < nrPolarizations; polarization++ ) {
          input[(channel * nrStations * nrSamples * nrPolarizations * 2) + (station * nrSamples * nrPolarizations * 2) + (sample * nrPolarizations * 2) + (polarization * 2)] = rand() % magicValue;
          input[(channel * nrStations * nrSamples * nrPolarizations * 2) + (station * nrSamples * nrPolarizations * 2) + (sample * nrPolarizations * 2) + (polarization * 2) + 1] = rand() % magicValue;
        }
      }
    }
  }
  // Compute CPU control results
  std::fill(output.begin(), output.end(), 0);
  TuneBench::correlator(input, output_c, nrChannels, nrStations, nrSamples, nrPolarizations);
  TuneBench::generateBaselineMap(baselineMap, nrStations);

  std::cout << std::fixed << std::endl;
  std::cout << "# nrChannels nrStations nrSamples nrPolarizations nrThreadsD0 nrItemsD0 nrItemsD1 GFLOP/s time stdDeviation COV" << std::endl << std::endl;

  for ( unsigned int threads = vectorSize; threads <= maxThreads; threads += vectorSize ) {
    conf.setNrThreadsD0(threads);
    for ( unsigned int threads = 1; (conf.getNrThreadsD0() * threads) <= maxThreads; threads++ ) {
      conf.setNrThreadsD2(threads);
      if ( nrChannels % conf.getNrThreadsD2() != 0 ) {
        continue;
      }
      for ( unsigned int items = 1; items <= maxItems; items++ ) {
        conf.setNrItemsD0(items);
        if ( nrSamples % (conf.getNrThreadsD0() * conf.getNrItemsD0()) != 0 ) {
          continue;
        }
        for ( unsigned int items = 1; items * 18 <= maxItems; items++ ) {
          conf.setNrItemsD1(items);
          if ( nrStations % conf.getNrItemsD1() != 0 ) {
            continue;
          }

          // Generate kernel
          double gflops = isa::utils::giga(static_cast< uint64_t >(nrChannels) * nrSamples * nrBaselines * 32);
          cl::Event clEvent;
          cl::Kernel * kernel;
          isa::utils::Timer timer;
          std::string * code = TuneBench::getCorrelatorOpenCL(conf, inputDataName, padding, nrChannels, nrStations, nrSamples, nrPolarizations);

          if ( reInit ) {
            delete clQueues;
            clQueues = new std::vector< std::vector< cl::CommandQueue > >();
            isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
            try {
              initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), &input, &input_d, nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2, &output_d, &baselineMap, &baselineMap_d);
            } catch ( cl::Error & err ) {
              return -1;
            }
            reInit = false;
          }
          try {
            kernel = isa::OpenCL::compile("correlator", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
          } catch ( isa::OpenCL::OpenCLError & err ) {
            std::cerr << err.what() << std::endl;
            delete code;
            break;
          }
          delete code;

          cl::NDRange global(nrSamples / conf.getNrItemsD0(), nrBaselines / conf.getNrItemsD1(), nrChannels);
          cl::NDRange local(conf.getNrThreadsD0(), 1, conf.getNrThreadsD2());

          kernel->setArg(0, input_d);
          kernel->setArg(1, output_d);

          try {
            // Warm-up run
            clQueues->at(clDeviceID)[0].finish();
            clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
            clEvent.wait();
            // Tuning runs
            for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
              timer.start();
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
              clEvent.wait();
              timer.stop();
            }
            clQueues->at(clDeviceID)[0].enqueueReadBuffer(output_d, CL_TRUE, 0, output.size() * sizeof(inputDataType), reinterpret_cast< void * >(output.data()), 0, &clEvent);
            clEvent.wait();
          } catch ( cl::Error & err ) {
            reInit = true;
            std::cerr << "OpenCL kernel execution error (";
            std::cerr << conf.print();
            std::cerr << "): ";
            std::cerr << std::to_string(err.err()) << std::endl;
            delete kernel;
            if ( err.err() == -4 || err.err() == -61 ) {
              return -1;
            }
            break;
          }
          delete kernel;

          bool error = false;
          for ( unsigned int item = 0; item < output_c.size(); item++ ) {
            if ( !isa::utils::same(output[item], output_c[item]) ) {
              std::cerr << "Output error (" << conf.print() << ")." << std::endl;
              error = true;
              break;
            }
          }
          if ( error ) {
            continue;
          }

          std::cout << nrChannels << " " << nrStations << " " << nrSamples << " " << nrPolarizations << " " ;
          std::cout << conf.print() << " ";
          std::cout << std::setprecision(3);
          std::cout << gflops / timer.getAverageTime() << " ";
          std::cout << std::setprecision(6);
          std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " " << timer.getCoefficientOfVariation() << std::endl;
        }
      }
    }
  }
  std::cout << std::endl;

  return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, const unsigned int outputSize, cl::Buffer * output_d, std::vector< unsigned int > * baselineMap, cl::Buffer * baselineMap_d) {
  try {
    *input_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, input->size() * sizeof(inputDataType), 0, 0);
    *output_d = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, outputSize * sizeof(inputDataType), 0, 0);
    *baselineMap_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, baselineMap->size() * sizeof(unsigned int), 0, 0);
    clQueue->enqueueWriteBuffer(*input_d, CL_FALSE, 0, input->size() * sizeof(inputDataType), reinterpret_cast< void * >(input->data()));
    clQueue->enqueueWriteBuffer(*baselineMap_d, CL_FALSE, 0, baselineMap->size() * sizeof(unsigned int), reinterpret_cast< void * >(baselineMap->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error (memory initialization): " << std::to_string(err.err()) << "." << std::endl;
    throw;
  }
}

<commit_msg>Forgot to set the last kernel's argument.<commit_after>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// 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 <vector>
#include <iostream>
#include <exception>
#include <iomanip>
#include <ctime>
#include <algorithm>

#include <configuration.hpp>

#include <ArgumentList.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Correlator.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

const unsigned int magicValue = 42;

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, const unsigned int outputSize, cl::Buffer * output_d, std::vector< unsigned int > * baselineMap, cl::Buffer * baselineMap_d);

int main(int argc, char * argv[]) {
  bool reInit = true;
  unsigned int padding = 0;
  unsigned int nrIterations = 0;
  unsigned int clPlatformID = 0;
  unsigned int clDeviceID = 0;
  unsigned int vectorSize = 0;
  unsigned int maxThreads = 0;
  unsigned int maxItems = 0;
  unsigned int nrChannels = 0;
  unsigned int nrStations = 0;
  unsigned int nrSamples = 0;
  isa::OpenCL::KernelConf conf;

  try {
    isa::utils::ArgumentList args(argc, argv);

    clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
    clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
    vectorSize = args.getSwitchArgument< unsigned int >("-vector");
    maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
    maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    nrChannels = args.getSwitchArgument< unsigned int >("-channels");
    nrStations = args.getSwitchArgument< unsigned int >("-stations");
    nrSamples = args.getSwitchArgument< unsigned int >("-samples");
  } catch ( isa::utils::EmptyCommandLine & err ) {
    std::cerr << argv[0] << " -opencl_platform ... -opencl_device ... -padding ... -iterations ... -vector ... -max_threads ... -max_items ... -channels ... -stations ... -samples ..." << std::endl;
    return 1;
  } catch ( std::exception & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  cl::Context clContext;
  std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
  std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
  std::vector< std::vector< cl::CommandQueue > > * clQueues = 0;

  // Allocate host memory
  unsigned int nrBaselines = (nrStations * (nrStations + 1)) / 2;
  std::vector< inputDataType > input(nrChannels * nrStations * nrSamples * nrPolarizations * 2);
  std::vector< inputDataType > output(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2), output_c(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2);
  std::vector< unsigned int > baselineMap(nrBaselines * 2);
  cl::Buffer input_d, output_d, baselineMap_d;

  // Populate data structures
  srand(time(0));
  for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
    for ( unsigned int station = 0; station < nrStations; station++ ) {
      for ( unsigned int sample = 0; sample < nrSamples; sample++ ) {
        for ( unsigned int polarization = 0; polarization < nrPolarizations; polarization++ ) {
          input[(channel * nrStations * nrSamples * nrPolarizations * 2) + (station * nrSamples * nrPolarizations * 2) + (sample * nrPolarizations * 2) + (polarization * 2)] = rand() % magicValue;
          input[(channel * nrStations * nrSamples * nrPolarizations * 2) + (station * nrSamples * nrPolarizations * 2) + (sample * nrPolarizations * 2) + (polarization * 2) + 1] = rand() % magicValue;
        }
      }
    }
  }
  // Compute CPU control results
  std::fill(output.begin(), output.end(), 0);
  TuneBench::correlator(input, output_c, nrChannels, nrStations, nrSamples, nrPolarizations);
  TuneBench::generateBaselineMap(baselineMap, nrStations);

  std::cout << std::fixed << std::endl;
  std::cout << "# nrChannels nrStations nrSamples nrPolarizations nrThreadsD0 nrItemsD0 nrItemsD1 GFLOP/s time stdDeviation COV" << std::endl << std::endl;

  for ( unsigned int threads = vectorSize; threads <= maxThreads; threads += vectorSize ) {
    conf.setNrThreadsD0(threads);
    for ( unsigned int threads = 1; (conf.getNrThreadsD0() * threads) <= maxThreads; threads++ ) {
      conf.setNrThreadsD2(threads);
      if ( nrChannels % conf.getNrThreadsD2() != 0 ) {
        continue;
      }
      for ( unsigned int items = 1; items <= maxItems; items++ ) {
        conf.setNrItemsD0(items);
        if ( nrSamples % (conf.getNrThreadsD0() * conf.getNrItemsD0()) != 0 ) {
          continue;
        }
        for ( unsigned int items = 1; items * 18 <= maxItems; items++ ) {
          conf.setNrItemsD1(items);
          if ( nrStations % conf.getNrItemsD1() != 0 ) {
            continue;
          }

          // Generate kernel
          double gflops = isa::utils::giga(static_cast< uint64_t >(nrChannels) * nrSamples * nrBaselines * 32);
          cl::Event clEvent;
          cl::Kernel * kernel;
          isa::utils::Timer timer;
          std::string * code = TuneBench::getCorrelatorOpenCL(conf, inputDataName, padding, nrChannels, nrStations, nrSamples, nrPolarizations);

          if ( reInit ) {
            delete clQueues;
            clQueues = new std::vector< std::vector< cl::CommandQueue > >();
            isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
            try {
              initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), &input, &input_d, nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2, &output_d, &baselineMap, &baselineMap_d);
            } catch ( cl::Error & err ) {
              return -1;
            }
            reInit = false;
          }
          try {
            kernel = isa::OpenCL::compile("correlator", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
          } catch ( isa::OpenCL::OpenCLError & err ) {
            std::cerr << err.what() << std::endl;
            delete code;
            break;
          }
          delete code;

          cl::NDRange global(nrSamples / conf.getNrItemsD0(), nrBaselines / conf.getNrItemsD1(), nrChannels);
          cl::NDRange local(conf.getNrThreadsD0(), 1, conf.getNrThreadsD2());

          kernel->setArg(0, input_d);
          kernel->setArg(1, output_d);
          kernel->setArg(2, baselineMap_d);

          try {
            // Warm-up run
            clQueues->at(clDeviceID)[0].finish();
            clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
            clEvent.wait();
            // Tuning runs
            for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
              timer.start();
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
              clEvent.wait();
              timer.stop();
            }
            clQueues->at(clDeviceID)[0].enqueueReadBuffer(output_d, CL_TRUE, 0, output.size() * sizeof(inputDataType), reinterpret_cast< void * >(output.data()), 0, &clEvent);
            clEvent.wait();
          } catch ( cl::Error & err ) {
            reInit = true;
            std::cerr << "OpenCL kernel execution error (";
            std::cerr << conf.print();
            std::cerr << "): ";
            std::cerr << std::to_string(err.err()) << std::endl;
            delete kernel;
            if ( err.err() == -4 || err.err() == -61 ) {
              return -1;
            }
            break;
          }
          delete kernel;

          bool error = false;
          for ( unsigned int item = 0; item < output_c.size(); item++ ) {
            if ( !isa::utils::same(output[item], output_c[item]) ) {
              std::cerr << "Output error (" << conf.print() << ")." << std::endl;
              error = true;
              break;
            }
          }
          if ( error ) {
            continue;
          }

          std::cout << nrChannels << " " << nrStations << " " << nrSamples << " " << nrPolarizations << " " ;
          std::cout << conf.print() << " ";
          std::cout << std::setprecision(3);
          std::cout << gflops / timer.getAverageTime() << " ";
          std::cout << std::setprecision(6);
          std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " " << timer.getCoefficientOfVariation() << std::endl;
        }
      }
    }
  }
  std::cout << std::endl;

  return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, const unsigned int outputSize, cl::Buffer * output_d, std::vector< unsigned int > * baselineMap, cl::Buffer * baselineMap_d) {
  try {
    *input_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, input->size() * sizeof(inputDataType), 0, 0);
    *output_d = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, outputSize * sizeof(inputDataType), 0, 0);
    *baselineMap_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, baselineMap->size() * sizeof(unsigned int), 0, 0);
    clQueue->enqueueWriteBuffer(*input_d, CL_FALSE, 0, input->size() * sizeof(inputDataType), reinterpret_cast< void * >(input->data()));
    clQueue->enqueueWriteBuffer(*baselineMap_d, CL_FALSE, 0, baselineMap->size() * sizeof(unsigned int), reinterpret_cast< void * >(baselineMap->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error (memory initialization): " << std::to_string(err.err()) << "." << std::endl;
    throw;
  }
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file libport/path.cc
 ** \brief Implement libport::path.
 */

#include <cctype>
#include <iostream>
#include <libport/cstdio>
#include <libport/debug.hh>
#include <libport/detect-win32.h>
#include <libport/exception.hh>
#include <libport/fcntl.h>
#include <libport/format.hh>
#include <libport/path.hh>
#include <libport/sys/stat.h>
#include <libport/sys/types.h>
#include <libport/unistd.h>

GD_CATEGORY(Libport.Path);

// Implementation detail: if components() is empty and not absolute
// then the path is '.'.

namespace boostfs = boost::filesystem;

namespace libport
{
  path::path(const std::string& p)
  {
    init(p);
  }

  path::path(const char* p)
  {
    init(p);
  }

  path::path(const value_type& p)
  {
    init(p.file_string());
  }

  void
  path::init(const std::string& p)
  {
    if (p.empty())
      throw invalid_path("Path can't be empty.");
#ifdef WIN32
    // We want "/" to mean "the root of the current volume" on windows.
    if (p[0] == '/')
      value_ = boost::filesystem::current_path().root_name() + p;
    else
#endif
    value_ = p;
    value_ = clean();
  }

  path&
  path::operator=(const path& rhs)
  {
    value_ = rhs.value_;
    return *this;
  }

  path&
  path::operator/=(const path& rhs)
  {
    if (rhs.absolute_get())
      throw invalid_path(
        "Rhs of concatenation is absolute: " + rhs.to_string());
#ifdef WIN32
    if (!rhs.volume_get().empty())
      throw invalid_path("concatenation of path with volume: " +
			 rhs.to_string());
#endif
    value_ /= rhs.value_;
    value_ = clean();
    return *this;
  }

  path
  path::operator/(const path& rhs) const
  {
    path res = *this;
    return res /= rhs;
  }

  std::string
  path::to_string() const
  {
    if (!value_.is_complete() && components().empty())
      return WIN32_IF(volume_get().empty() ? "." : volume_get(), ".");

    return value_.file_string();
  }

  bool
  path::operator==(const path& rhs) const
  {
    return (volume_get() == rhs.volume_get()
            && absolute_get() == rhs.absolute_get()
            && components() == rhs.components());
  }

  std::ostream&
  path::dump(std::ostream& o) const
  {
    return o << operator std::string();
  }

  bool
  path::is_dir() const
  {
    return boostfs::is_directory(to_string());
  }

  bool
  path::is_reg() const
  {
    return boostfs::is_regular_file(to_string());
  }

  std::string
  path::clean() const
  {
    std::string res;
    value_type::iterator i = value_.begin();
    value_type::iterator i_end = value_.end();
    if (i == i_end)
      return ".";

    bool first = true;
    if (absolute_get())
    {
      res = *i;
      ++i;
#ifdef WIN32
      // Add a "\" after the drive letter or network share.
      first = false;
#endif
    }

    for (;i != i_end; ++i)
    {
      // Remove the "." and empty components.
      if (!i->empty() && *i != ".")
      {
        if (!first)
          res += separator_;
        first = false;
        res += *i;
      }
    }
    return res.empty() ? "." : res;
  }

  std::string
  path::volume_get() const
  {
#ifndef WIN32
    return "";
#else
    std::string res = value_.root_name();
    if (res.find("//") == 0)
      res.replace(0, 2, "\\\\");
    return res;
#endif
  }

  path
  path::dirname() const
  {
    // dirname of / is /, dirname of . is .
    if (components().empty())
      return *this;

    std::string res = value_.parent_path().directory_string();
    return path(res.empty() ? "." : res);
  }

  bool path::exists() const
  {
    bool res;
    try
    {
      res = boost::filesystem::exists(value_);
    }
    catch (...)
    {
      res = false;
    }
    GD_FINFO_DUMP("exists: %-5s: %s", res ? "true" : "false", to_string());
    return res;
  }

  path
  path::cwd()
  {
    return path(boost::filesystem::current_path().string());
  }

  bool
  path::is_root() const
  {
    return to_string() == (volume_get() + separator_);
  }

  path
  path::parent() const
  {
    if (is_root())
      return path(volume_get().append(1, separator_));

    const std::string parent_path =
      boost::filesystem::path(to_string()).parent_path().string();

    if (parent_path.empty())
      return cwd();

    return parent_path;
  }

  std::time_t
  path::last_write_time() const
  {
    return boost::filesystem::last_write_time(
      boost::filesystem::path(to_string()));
  }

  bool path::create() const
  {
    int fd = open(to_string().c_str(),
                  O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
    if (fd == -1)
      return false;
    close(fd);
    return true;
  }

  path
  path::temporary_file()
  {
#ifndef WIN32
    char tmp_name[] = "/tmp/tmp.XXXXXX";
    int fd = mkstemp(tmp_name);
    close (fd);
#else
    char tmp_dir[MAX_PATH];
    char tmp_name[MAX_PATH];

    if(GetTempPathA(sizeof(tmp_dir), tmp_dir) == 0
       || GetTempFileNameA(tmp_dir, "$$$", 0, tmp_name) == 0)
      throw Exception("cannot generate path for temporary file");
#endif
    return path(tmp_name);
  }

  void
  path::remove() const
  {
    if (!boost::filesystem::remove(value_))
      throw Exception(libport::format("cannot unlink file %s", *this));
  }

  void
  path::rename(const std::string& dst)
  {
    try
    {
      boost::filesystem::rename(value_, dst);
    }
    catch (Exception& e)
    {
      throw Exception(libport::format("cannot rename directory %s: %s",
                                      *this, format_boost_fs_error(e.what())));
    }

    *this = dst;
  }

  path::path_type
  path::components() const
  {
    path_type path_;
    value_type::iterator
      i = value_.begin(),
      i_end = value_.end();
    if (i == i_end)
      return path_;

    // Skip volume information.
    if (absolute_get())
    {
      ++i;
#ifdef WIN32 // Skip a / after the volume information.
      ++i;
#endif
    }
    for (;i != i_end; ++i)
      if (!i->empty() && *i != ".")
        path_.push_back(*i);

    return path_;
  }

  std::string
  format_boost_fs_error(const char* what)
  {
    static const std::string ns = "boost::filesystem::";
    // Get rid of function namespace.
    std::string error = std::string(what).substr(ns.size());
    // Get rid of function name and ": ".
    error = error.substr(error.find(":") + 2);
    // Urbi errors begin with a lower case letter.
    error[0] = tolower(error[0]);
    return error;
  }
}
<commit_msg>libport: use boostfs instead of boost::filesytem.<commit_after>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file libport/path.cc
 ** \brief Implement libport::path.
 */

#include <cctype>
#include <iostream>
#include <libport/cstdio>
#include <libport/debug.hh>
#include <libport/detect-win32.h>
#include <libport/exception.hh>
#include <libport/fcntl.h>
#include <libport/format.hh>
#include <libport/path.hh>
#include <libport/sys/stat.h>
#include <libport/sys/types.h>
#include <libport/unistd.h>

GD_CATEGORY(Libport.Path);

// Implementation detail: if components() is empty and not absolute
// then the path is '.'.

namespace boostfs = boost::filesystem;

namespace libport
{
  path::path(const std::string& p)
  {
    init(p);
  }

  path::path(const char* p)
  {
    init(p);
  }

  path::path(const value_type& p)
  {
    init(p.file_string());
  }

  void
  path::init(const std::string& p)
  {
    if (p.empty())
      throw invalid_path("Path can't be empty.");
#ifdef WIN32
    // We want "/" to mean "the root of the current volume" on windows.
    if (p[0] == '/')
      value_ = boostfs::current_path().root_name() + p;
    else
#endif
    value_ = p;
    value_ = clean();
  }

  path&
  path::operator=(const path& rhs)
  {
    value_ = rhs.value_;
    return *this;
  }

  path&
  path::operator/=(const path& rhs)
  {
    if (rhs.absolute_get())
      throw invalid_path(
        "Rhs of concatenation is absolute: " + rhs.to_string());
#ifdef WIN32
    if (!rhs.volume_get().empty())
      throw invalid_path("concatenation of path with volume: " +
			 rhs.to_string());
#endif
    value_ /= rhs.value_;
    value_ = clean();
    return *this;
  }

  path
  path::operator/(const path& rhs) const
  {
    path res = *this;
    return res /= rhs;
  }

  std::string
  path::to_string() const
  {
    if (!value_.is_complete() && components().empty())
      return WIN32_IF(volume_get().empty() ? "." : volume_get(), ".");

    return value_.file_string();
  }

  bool
  path::operator==(const path& rhs) const
  {
    return (volume_get() == rhs.volume_get()
            && absolute_get() == rhs.absolute_get()
            && components() == rhs.components());
  }

  std::ostream&
  path::dump(std::ostream& o) const
  {
    return o << operator std::string();
  }

  bool
  path::is_dir() const
  {
    return boostfs::is_directory(to_string());
  }

  bool
  path::is_reg() const
  {
    return boostfs::is_regular_file(to_string());
  }

  std::string
  path::clean() const
  {
    std::string res;
    value_type::iterator i = value_.begin();
    value_type::iterator i_end = value_.end();
    if (i == i_end)
      return ".";

    bool first = true;
    if (absolute_get())
    {
      res = *i;
      ++i;
#ifdef WIN32
      // Add a "\" after the drive letter or network share.
      first = false;
#endif
    }

    for (;i != i_end; ++i)
    {
      // Remove the "." and empty components.
      if (!i->empty() && *i != ".")
      {
        if (!first)
          res += separator_;
        first = false;
        res += *i;
      }
    }
    return res.empty() ? "." : res;
  }

  std::string
  path::volume_get() const
  {
#ifndef WIN32
    return "";
#else
    std::string res = value_.root_name();
    if (res.find("//") == 0)
      res.replace(0, 2, "\\\\");
    return res;
#endif
  }

  path
  path::dirname() const
  {
    // dirname of / is /, dirname of . is .
    if (components().empty())
      return *this;

    std::string res = value_.parent_path().directory_string();
    return path(res.empty() ? "." : res);
  }

  bool path::exists() const
  {
    bool res;
    try
    {
      res = boostfs::exists(value_);
    }
    catch (...)
    {
      res = false;
    }
    GD_FINFO_DUMP("exists: %-5s: %s", res ? "true" : "false", to_string());
    return res;
  }

  path
  path::cwd()
  {
    return path(boostfs::current_path().string());
  }

  bool
  path::is_root() const
  {
    return to_string() == (volume_get() + separator_);
  }

  path
  path::parent() const
  {
    if (is_root())
      return path(volume_get().append(1, separator_));

    const std::string parent_path =
      boostfs::path(to_string()).parent_path().string();

    if (parent_path.empty())
      return cwd();

    return parent_path;
  }

  std::time_t
  path::last_write_time() const
  {
    return boostfs::last_write_time(
      boostfs::path(to_string()));
  }

  bool path::create() const
  {
    int fd = open(to_string().c_str(),
                  O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
    if (fd == -1)
      return false;
    close(fd);
    return true;
  }

  path
  path::temporary_file()
  {
#ifndef WIN32
    char tmp_name[] = "/tmp/tmp.XXXXXX";
    int fd = mkstemp(tmp_name);
    close (fd);
#else
    char tmp_dir[MAX_PATH];
    char tmp_name[MAX_PATH];

    if(GetTempPathA(sizeof(tmp_dir), tmp_dir) == 0
       || GetTempFileNameA(tmp_dir, "$$$", 0, tmp_name) == 0)
      throw Exception("cannot generate path for temporary file");
#endif
    return path(tmp_name);
  }

  void
  path::remove() const
  {
    if (!boostfs::remove(value_))
      throw Exception(libport::format("cannot unlink file %s", *this));
  }

  void
  path::rename(const std::string& dst)
  {
    try
    {
      boostfs::rename(value_, dst);
    }
    catch (Exception& e)
    {
      throw Exception(libport::format("cannot rename directory %s: %s",
                                      *this, format_boost_fs_error(e.what())));
    }

    *this = dst;
  }

  path::path_type
  path::components() const
  {
    path_type path_;
    value_type::iterator
      i = value_.begin(),
      i_end = value_.end();
    if (i == i_end)
      return path_;

    // Skip volume information.
    if (absolute_get())
    {
      ++i;
#ifdef WIN32 // Skip a / after the volume information.
      ++i;
#endif
    }
    for (;i != i_end; ++i)
      if (!i->empty() && *i != ".")
        path_.push_back(*i);

    return path_;
  }

  std::string
  format_boost_fs_error(const char* what)
  {
    static const std::string ns = "boost::filesystem::";
    // Get rid of function namespace.
    std::string error = std::string(what).substr(ns.size());
    // Get rid of function name and ": ".
    error = error.substr(error.find(":") + 2);
    // Urbi errors begin with a lower case letter.
    error[0] = tolower(error[0]);
    return error;
  }
}
<|endoftext|>


<commit_before>/* GG is a GUI for SDL and OpenGL.
   Copyright (C) 2003 T. Zachary Laine

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1
   of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   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

   If you do not wish to comply with the terms of the LGPL please
   contact the author as other terms are available for a fee.

   Zach Laine
   whatwasthataddress@hotmail.com */

/* $Header$ */

#include "GGDropDownList.h"

#include <GGScroll.h>
#include <GGApp.h>
#include <GGDrawUtil.h>
#include <XMLValidators.h>

using namespace GG;

namespace {
    const int BORDER_THICK = 2; // should be the same as the BORDER_THICK value in GGListBox.h

    class ModalListPicker : public Wnd
    {
    public:
        ModalListPicker(DropDownList* drop_wnd, ListBox* lb_wnd) :
            Wnd(0, 0, GG::App::GetApp()->AppWidth() - 1, GG::App::GetApp()->AppHeight() - 1, CLICKABLE | MODAL),
            m_drop_wnd(drop_wnd),
            m_lb_wnd(lb_wnd),
            m_old_lb_ul(m_lb_wnd->UpperLeft())
        {
            Connect(m_lb_wnd->SelChangedSignal(), &ModalListPicker::LBSelChangedSlot, this);
            Connect(m_lb_wnd->LeftClickedSignal(), &ModalListPicker::LBLeftClickSlot, this);
            m_lb_wnd->OffsetMove(m_drop_wnd->Parent() ? m_drop_wnd->Parent()->UpperLeft() : Pt());
            AttachChild(m_lb_wnd);
        }
        ~ModalListPicker() {m_lb_wnd->MoveTo(m_old_lb_ul); DetachChild(m_lb_wnd);}

    protected:
        virtual void LClick(const Pt& pt, Uint32 keys) {m_done = true;}

    private:
        void LBSelChangedSlot(const set<int>& rows)
        {
            if (!rows.empty()) {
                m_drop_wnd->Select(*rows.begin());
                m_done = true;
            }
        }
        void LBLeftClickSlot(int, const ListBox::Row*, const Pt&)
        {
            m_done = true;
        }

        DropDownList*  m_drop_wnd;
        ListBox*       m_lb_wnd;
        Pt             m_old_lb_ul;
    };
}

DropDownList::DropDownList(int x, int y, int w, int row_ht, int drop_ht, Clr color, ListBox* lb/* = 0*/,
                           Uint32 flags/* = CLICKABLE*/) :
    Control(x, y, w, row_ht, flags),
    m_current_item_idx(-1),
    m_LB(lb)
{
    if (!m_LB)
        m_LB = new ListBox(x, y, w, drop_ht, color, color, flags);
    m_LB->SetRowHeight(row_ht);
    SetStyle(LB_SINGLESEL);
    // adjust size to keep correct height based on row height, etc.
    Resize(Size().x, row_ht + 2 * m_LB->CellMargin() + 2 * BORDER_THICK);
    m_LB->MoveTo(x, y + Height());
}

DropDownList::DropDownList(int x, int y, int w, int row_ht, int drop_ht, Clr color, Clr interior,
                           ListBox* lb/* = 0*/, Uint32 flags/* = CLICKABLE*/) :
    Control(x, y, w, row_ht, flags),
    m_current_item_idx(-1),
    m_LB(lb)
{
    if (!m_LB)
        m_LB = new ListBox(x, y, w, drop_ht, color, interior, flags);
    m_LB->SetRowHeight(row_ht);
    SetStyle(LB_SINGLESEL);
    // adjust size to keep correct height based on row height, etc.
    Resize(Size().x, row_ht + 2 * m_LB->CellMargin() + 2 * BORDER_THICK);
    m_LB->MoveTo(x, y + Height());
}

DropDownList::DropDownList(const XMLElement& elem) :
    Control(elem.Child("GG::Control"))
{
    if (elem.Tag() != "GG::DropDownList")
        throw std::invalid_argument("Attempted to construct a GG::DropDownList from an XMLElement that had a tag other than \"GG::DropDownList\"");

    m_current_item_idx = lexical_cast<int>(elem.Child("m_current_item_idx").Text());

    if (ListBox* lb = dynamic_cast<ListBox*>(App::GetApp()->GenerateWnd(elem.Child("m_LB").Child(0)))) {
        m_LB = lb;
    } else {
        throw std::runtime_error("DropDownList::DropDownList : Attempted to use a non-ListBox object as the drop-down list.");
    }
}

DropDownList::~DropDownList()
{
    delete m_LB;
}

const DropDownList::Row* DropDownList::CurrentItem() const
{
    return m_current_item_idx == -1 ? 0 : &m_LB->GetRow(m_current_item_idx);
}

bool DropDownList::Render()
{
    // draw beveled rectangle around client area
    Pt ul = UpperLeft(), lr = LowerRight();
    Clr color_to_use = Disabled() ? DisabledColor(m_LB->Color()) : m_LB->Color();
    Clr int_color_to_use = Disabled() ? DisabledColor(m_LB->m_int_color) : m_LB->m_int_color;

    BeveledRectangle(ul.x, ul.y, lr.x, lr.y, int_color_to_use, color_to_use, false, BORDER_THICK);

    // draw ListBox::Row of currently displayed item, if any
    const Row* current_item = CurrentItem();
    if (current_item) {
        // clip row to viewable area, and save old scissor state
        glPushAttrib(GL_SCISSOR_BIT);
        glEnable(GL_SCISSOR_TEST);
        glScissor(ul.x + BORDER_THICK, App::GetApp()->AppHeight() - lr.y + BORDER_THICK,
                  lr.x - ul.x - 2 * BORDER_THICK,
                  lr.y - ul.y - 2 * BORDER_THICK);

        m_LB->RenderRow(current_item, ul.x + BORDER_THICK, ul.y + BORDER_THICK, m_LB->LastVisibleCol());

        // restore previous scissor-clipping state
        glPopAttrib();
    }

    return true;
}

void DropDownList::LClick(const Pt& pt, Uint32 keys)
{
    if (!Disabled()) {
        ModalListPicker picker(this, m_LB);
        const set<int>& LB_sels = m_LB->Selections();
        if (!LB_sels.empty()) {
            if (m_LB->m_vscroll)
                m_LB->m_vscroll->ScrollTo(*LB_sels.begin() * m_LB->RowHeight());
        }
        m_LB->m_first_col_shown = 0;
        picker.Run();
    }
}

void DropDownList::Keypress(Key key, Uint32 key_mods)
{
    if (!Disabled()) {
        switch (key) {
        case GGK_UP: // arrow-up (not numpad arrow)
            if (1 <= m_current_item_idx)
                Select(std::max(0, m_current_item_idx - 1));
            break;
        case GGK_DOWN: // arrow-down (not numpad arrow)
            if (m_current_item_idx < m_LB->NumRows())
                Select(std::min(m_current_item_idx + 1, m_LB->NumRows() - 1));
            break;
        case GGK_PAGEUP: // page up key (not numpad key)
            if (m_LB->NumRows())
                Select(std::max(0, m_current_item_idx - 10));
            break;
        case GGK_PAGEDOWN: // page down key (not numpad key)
            if (m_LB->NumRows())
                Select(std::min(m_current_item_idx + 10, m_LB->NumRows() - 1));
            break;
        case GGK_HOME: // home key (not numpad)
            if (m_LB->NumRows())
                Select(0);
            break;
        case GGK_END: // end key (not numpad)
            if (m_LB->NumRows())
                Select(m_LB->NumRows() - 1);
            break;
        default: // any other key gets passed along to the parent
            if (Parent())
                Parent()->Keypress(key, key_mods);
        }
    } else {
        if (Parent())
            Parent()->Keypress(key, key_mods);
    }
}

void DropDownList::SizeMove(int x1, int y1, int x2, int y2)
{
    // adjust size to keep correct height based on row height, etc.
    Wnd::SizeMove(x1, y1, x2, y1 + m_LB->RowHeight() + 2 * m_LB->CellMargin() + 2 * BORDER_THICK);
    m_LB->Resize(Width(), m_LB->Height());
    m_LB->MoveTo(x1, y1 + Height());
}

int DropDownList::Insert(Row* row, int at/* = -1*/)
{
    row->height = m_LB->RowHeight();
    row->sub_rows.clear();
    return m_LB->Insert(row, at);
}

void DropDownList::Delete(int idx)
{
    if (idx == m_current_item_idx)
        m_current_item_idx = -1;
    else if (idx < m_current_item_idx)
        --m_current_item_idx;

    m_LB->Delete(idx);
}

void DropDownList::Clear()
{
    m_current_item_idx = -1;
    m_LB->Clear();
}

void DropDownList::Select(int row)
{
    int old_m_current_item_idx = m_current_item_idx;
    if (row <= -1 || m_LB->NumRows() <= row) {
        m_current_item_idx = -1;
        m_LB->ClearSelection();
    } else {
        m_current_item_idx = row;
        m_LB->SelectRow(m_current_item_idx);
    }

    if (m_current_item_idx != old_m_current_item_idx)
        m_sel_changed_sig(m_current_item_idx);
}

void DropDownList::SetStyle(Uint32 s)
{
    s &= ~(LB_NOSEL | LB_QUICKSEL | LB_DRAGDROP | LB_USERDELETE | LB_BROWSEUPDATES);
    s |= LB_SINGLESEL;
    m_LB->SetStyle(s);
    m_current_item_idx = -1;
}

void DropDownList::SetSortCol(int n)
{
    m_LB->SetSortCol(n);
    m_current_item_idx = -1;
}

XMLElement DropDownList::XMLEncode() const
{
    XMLElement retval("GG::DropDownList");
    retval.AppendChild(Control::XMLEncode());
    retval.AppendChild(XMLElement("m_current_item_idx", lexical_cast<string>(m_current_item_idx)));
    retval.AppendChild(XMLElement("m_LB", m_LB->XMLEncode()));
    return retval;
}

XMLElementValidator DropDownList::XMLValidator() const
{
    XMLElementValidator retval("GG::DropDownList");
    retval.AppendChild(Control::XMLValidator());
    retval.AppendChild(XMLElementValidator("m_current_item_idx", new Validator<int>()));
    retval.AppendChild(XMLElementValidator("m_LB", m_LB->XMLValidator()));
    return retval;
}
<commit_msg>Corrected the placement of the drop-list, so DropDownLists work equally well as stand-alone controls and in ListBox::Row cells.<commit_after>/* GG is a GUI for SDL and OpenGL.
   Copyright (C) 2003 T. Zachary Laine

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1
   of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   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

   If you do not wish to comply with the terms of the LGPL please
   contact the author as other terms are available for a fee.

   Zach Laine
   whatwasthataddress@hotmail.com */

/* $Header$ */

#include "GGDropDownList.h"

#include <GGScroll.h>
#include <GGApp.h>
#include <GGDrawUtil.h>
#include <XMLValidators.h>

using namespace GG;

namespace {
    const int BORDER_THICK = 2; // should be the same as the BORDER_THICK value in GGListBox.h

    class ModalListPicker : public Wnd
    {
    public:
        ModalListPicker(DropDownList* drop_wnd, ListBox* lb_wnd) :
            Wnd(0, 0, GG::App::GetApp()->AppWidth() - 1, GG::App::GetApp()->AppHeight() - 1, CLICKABLE | MODAL),
            m_drop_wnd(drop_wnd),
            m_lb_wnd(lb_wnd),
            m_old_lb_ul(m_lb_wnd->UpperLeft())
        {
            Connect(m_lb_wnd->SelChangedSignal(), &ModalListPicker::LBSelChangedSlot, this);
            Connect(m_lb_wnd->LeftClickedSignal(), &ModalListPicker::LBLeftClickSlot, this);
            m_lb_wnd->OffsetMove(m_drop_wnd->ClientUpperLeft());
            AttachChild(m_lb_wnd);
        }
        ~ModalListPicker() {m_lb_wnd->MoveTo(m_old_lb_ul); DetachChild(m_lb_wnd);}

    protected:
        virtual void LClick(const Pt& pt, Uint32 keys) {m_done = true;}

    private:
        void LBSelChangedSlot(const set<int>& rows)
        {
            if (!rows.empty()) {
                m_drop_wnd->Select(*rows.begin());
                m_done = true;
            }
        }
        void LBLeftClickSlot(int, const ListBox::Row*, const Pt&)
        {
            m_done = true;
        }

        DropDownList*  m_drop_wnd;
        ListBox*       m_lb_wnd;
        Pt             m_old_lb_ul;
    };
}

DropDownList::DropDownList(int x, int y, int w, int row_ht, int drop_ht, Clr color, ListBox* lb/* = 0*/,
                           Uint32 flags/* = CLICKABLE*/) :
    Control(x, y, w, row_ht, flags),
    m_current_item_idx(-1),
    m_LB(lb)
{
    if (!m_LB)
        m_LB = new ListBox(x, y, w, drop_ht, color, color, flags);
    m_LB->SetRowHeight(row_ht);
    SetStyle(LB_SINGLESEL);
    // adjust size to keep correct height based on row height, etc.
    Resize(Size().x, row_ht + 2 * m_LB->CellMargin() + 2 * BORDER_THICK);
    m_LB->MoveTo(x, y + Height());
}

DropDownList::DropDownList(int x, int y, int w, int row_ht, int drop_ht, Clr color, Clr interior,
                           ListBox* lb/* = 0*/, Uint32 flags/* = CLICKABLE*/) :
    Control(x, y, w, row_ht, flags),
    m_current_item_idx(-1),
    m_LB(lb)
{
    if (!m_LB)
        m_LB = new ListBox(x, y, w, drop_ht, color, interior, flags);
    m_LB->SetRowHeight(row_ht);
    SetStyle(LB_SINGLESEL);
    // adjust size to keep correct height based on row height, etc.
    Resize(Size().x, row_ht + 2 * m_LB->CellMargin() + 2 * BORDER_THICK);
    m_LB->MoveTo(x, y + Height());
}

DropDownList::DropDownList(const XMLElement& elem) :
    Control(elem.Child("GG::Control"))
{
    if (elem.Tag() != "GG::DropDownList")
        throw std::invalid_argument("Attempted to construct a GG::DropDownList from an XMLElement that had a tag other than \"GG::DropDownList\"");

    m_current_item_idx = lexical_cast<int>(elem.Child("m_current_item_idx").Text());

    if (ListBox* lb = dynamic_cast<ListBox*>(App::GetApp()->GenerateWnd(elem.Child("m_LB").Child(0)))) {
        m_LB = lb;
    } else {
        throw std::runtime_error("DropDownList::DropDownList : Attempted to use a non-ListBox object as the drop-down list.");
    }
}

DropDownList::~DropDownList()
{
    delete m_LB;
}

const DropDownList::Row* DropDownList::CurrentItem() const
{
    return m_current_item_idx == -1 ? 0 : &m_LB->GetRow(m_current_item_idx);
}

bool DropDownList::Render()
{
    // draw beveled rectangle around client area
    Pt ul = UpperLeft(), lr = LowerRight();
    Clr color_to_use = Disabled() ? DisabledColor(m_LB->Color()) : m_LB->Color();
    Clr int_color_to_use = Disabled() ? DisabledColor(m_LB->m_int_color) : m_LB->m_int_color;

    BeveledRectangle(ul.x, ul.y, lr.x, lr.y, int_color_to_use, color_to_use, false, BORDER_THICK);

    // draw ListBox::Row of currently displayed item, if any
    const Row* current_item = CurrentItem();
    if (current_item) {
        // clip row to viewable area, and save old scissor state
        glPushAttrib(GL_SCISSOR_BIT);
        glEnable(GL_SCISSOR_TEST);
        glScissor(ul.x + BORDER_THICK, App::GetApp()->AppHeight() - lr.y + BORDER_THICK,
                  lr.x - ul.x - 2 * BORDER_THICK,
                  lr.y - ul.y - 2 * BORDER_THICK);

        m_LB->RenderRow(current_item, ul.x + BORDER_THICK, ul.y + BORDER_THICK, m_LB->LastVisibleCol());

        // restore previous scissor-clipping state
        glPopAttrib();
    }

    return true;
}

void DropDownList::LClick(const Pt& pt, Uint32 keys)
{
    if (!Disabled()) {
        ModalListPicker picker(this, m_LB);
        const set<int>& LB_sels = m_LB->Selections();
        if (!LB_sels.empty()) {
            if (m_LB->m_vscroll)
                m_LB->m_vscroll->ScrollTo(*LB_sels.begin() * m_LB->RowHeight());
        }
        m_LB->m_first_col_shown = 0;
        picker.Run();
    }
}

void DropDownList::Keypress(Key key, Uint32 key_mods)
{
    if (!Disabled()) {
        switch (key) {
        case GGK_UP: // arrow-up (not numpad arrow)
            if (1 <= m_current_item_idx)
                Select(std::max(0, m_current_item_idx - 1));
            break;
        case GGK_DOWN: // arrow-down (not numpad arrow)
            if (m_current_item_idx < m_LB->NumRows())
                Select(std::min(m_current_item_idx + 1, m_LB->NumRows() - 1));
            break;
        case GGK_PAGEUP: // page up key (not numpad key)
            if (m_LB->NumRows())
                Select(std::max(0, m_current_item_idx - 10));
            break;
        case GGK_PAGEDOWN: // page down key (not numpad key)
            if (m_LB->NumRows())
                Select(std::min(m_current_item_idx + 10, m_LB->NumRows() - 1));
            break;
        case GGK_HOME: // home key (not numpad)
            if (m_LB->NumRows())
                Select(0);
            break;
        case GGK_END: // end key (not numpad)
            if (m_LB->NumRows())
                Select(m_LB->NumRows() - 1);
            break;
        default: // any other key gets passed along to the parent
            if (Parent())
                Parent()->Keypress(key, key_mods);
        }
    } else {
        if (Parent())
            Parent()->Keypress(key, key_mods);
    }
}

void DropDownList::SizeMove(int x1, int y1, int x2, int y2)
{
    // adjust size to keep correct height based on row height, etc.
    Wnd::SizeMove(x1, y1, x2, y1 + m_LB->RowHeight() + 2 * m_LB->CellMargin() + 2 * BORDER_THICK);
    m_LB->SizeMove(0, Height(), Width(), Height() + m_LB->Height());
}

int DropDownList::Insert(Row* row, int at/* = -1*/)
{
    row->height = m_LB->RowHeight();
    row->sub_rows.clear();
    return m_LB->Insert(row, at);
}

void DropDownList::Delete(int idx)
{
    if (idx == m_current_item_idx)
        m_current_item_idx = -1;
    else if (idx < m_current_item_idx)
        --m_current_item_idx;

    m_LB->Delete(idx);
}

void DropDownList::Clear()
{
    m_current_item_idx = -1;
    m_LB->Clear();
}

void DropDownList::Select(int row)
{
    int old_m_current_item_idx = m_current_item_idx;
    if (row <= -1 || m_LB->NumRows() <= row) {
        m_current_item_idx = -1;
        m_LB->ClearSelection();
    } else {
        m_current_item_idx = row;
        m_LB->SelectRow(m_current_item_idx);
    }

    if (m_current_item_idx != old_m_current_item_idx)
        m_sel_changed_sig(m_current_item_idx);
}

void DropDownList::SetStyle(Uint32 s)
{
    s &= ~(LB_NOSEL | LB_QUICKSEL | LB_DRAGDROP | LB_USERDELETE | LB_BROWSEUPDATES);
    s |= LB_SINGLESEL;
    m_LB->SetStyle(s);
    m_current_item_idx = -1;
}

void DropDownList::SetSortCol(int n)
{
    m_LB->SetSortCol(n);
    m_current_item_idx = -1;
}

XMLElement DropDownList::XMLEncode() const
{
    XMLElement retval("GG::DropDownList");
    retval.AppendChild(Control::XMLEncode());
    retval.AppendChild(XMLElement("m_current_item_idx", lexical_cast<string>(m_current_item_idx)));
    retval.AppendChild(XMLElement("m_LB", m_LB->XMLEncode()));
    return retval;
}

XMLElementValidator DropDownList::XMLValidator() const
{
    XMLElementValidator retval("GG::DropDownList");
    retval.AppendChild(Control::XMLValidator());
    retval.AppendChild(XMLElementValidator("m_current_item_idx", new Validator<int>()));
    retval.AppendChild(XMLElementValidator("m_LB", m_LB->XMLValidator()));
    return retval;
}
<|endoftext|>


<commit_before>// @(#)root/qtgsi:$Id$
// Author: Denis Bertini, M. Al-Turany  01/11/2000

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "qevent.h"
#include "qdialog.h"
#include "qpushbutton.h"
#include "qlabel.h"
#include "qpainter.h"
#if  (QT_VERSION > 0x039999) // Added by cholm@nbi.dk - for Qt 4
# include "qmenu.h"
# include "q3popupmenu.h"
typedef Q3PopupMenu QPopupMenu;
#else
# include "qpopupmenu.h"
#endif

#include "TQCanvasMenu.h"
#include "TClass.h"
#include "TROOT.h"
#include "TMethod.h"
#include "TMethodCall.h"
#include "TMethodArg.h"
#include "TCanvas.h"
#include "TDataType.h"
#include "TQRootDialog.h"

ClassImp(TQCanvasMenu)

//______________________________________________________________________________
TQCanvasMenu::TQCanvasMenu(QWidget* parent, TCanvas *canvas)
{
   // ctor, create the popup menu

   fc       = canvas;
   fPopup   = new QPopupMenu;
   fCurrObj = 0;
   fParent  = parent;
   fTabWin  = 0;
   fDialog  = 0;
   fMousePosX = fMousePosY = 0;
}

//______________________________________________________________________________
TQCanvasMenu::TQCanvasMenu(QWidget* parent, QWidget *tabWin, TCanvas *canvas)
{
   // ctor, create the popup menu

   fc       = canvas;
   fPopup   = new QPopupMenu;
   fParent  = parent;
   fTabWin  = tabWin;
   fCurrObj = 0;
   fDialog  = 0;
   fMousePosX = fMousePosY = 0;
}

//______________________________________________________________________________
TQCanvasMenu::~TQCanvasMenu()
{
   // dtor

   if (fPopup) delete fPopup;
}

//______________________________________________________________________________
char *TQCanvasMenu::CreateDialogTitle( TObject *object, TMethod *method )
{
   // Create title for dialog box retrieving argument values.

   static char methodTitle[128];

   if (object && method)
      snprintf(methodTitle, 127, "%s::%s", object->ClassName(), method->GetName());
   else
      *methodTitle = 0;
   return methodTitle;

}

//______________________________________________________________________________
char *TQCanvasMenu::CreateArgumentTitle(TMethodArg *argument)
{
   // Create string describing argument (for use in dialog box).

   static Char_t argTitle[128];
   if (argument) {
      snprintf(argTitle, 127, "(%s)  %s", argument->GetTitle(), argument->GetName());
      const char *arg_def = argument->GetDefault();
      if (arg_def && *arg_def) {
         strncat(argTitle, "  [default: ", 127 - strlen(argTitle));
         strncat(argTitle, arg_def, 127 - strlen(argTitle));
         strncat(argTitle, "]", 127 - strlen(argTitle));
      }
   }
   else
      *argTitle = 0;

   return argTitle;
}

//______________________________________________________________________________
void TQCanvasMenu::Popup(TObject *obj, double x, double y, QMouseEvent *e)
{
   // Perform the corresponding selected TObject  popup
   // in the position defined
   // by x, y coordinates (in user coordinate system).
   // @param obj (TObject*)
   // @param p (QPoint&)

   TClass *klass=obj->IsA();
   Int_t curId=-1;

   fCurrObj=obj;
   fPopup->clear();
   fMethods.Clear();

   QString buffer=klass->GetName();
   buffer+="::";
   buffer+=obj->GetName();
   fPopup->insertItem(buffer, this, SLOT( Execute(int) ), 0,curId); curId++;
   klass->GetMenuItems(&fMethods);
   fPopup->insertSeparator();
   TIter iter(&fMethods);
   TMethod *method=0;
   while ( (method = dynamic_cast<TMethod*>(iter())) != 0) {
      buffer=method->GetName();
      fPopup->insertItem(buffer, this, SLOT( Execute(int) ), 0,curId);
      curId++;
   }
   // hold the position where the mouse was clicked
   fMousePosX= x;
   fMousePosY= y;

   // let Qt decide how to draw the popup Menu otherwise we have a problem that
   // the visible rectangle can get outside the screen (M.T. 03.06.02)
   fPopup->popup(e->globalPos(), 0);

}

//______________________________________________________________________________
void TQCanvasMenu::Execute(int id)
{
   // Slot defined to execute a method from a selected TObject
   // using TObject::Execute() function.

   QString text="";

   TVirtualPad  *psave = gROOT->GetSelectedPad();
   TMethod *method=(TMethod *)fMethods.At(id);
   fc->HandleInput(kButton3Up,gPad->XtoAbsPixel(fMousePosX), gPad->YtoAbsPixel(fMousePosY) );
   if (  method->GetListOfMethodArgs()->First() ) {
      Dialog(fCurrObj,method);
   }
   else {
      gROOT->SetFromPopUp(kTRUE);
      fCurrObj->Execute((char *) method->GetName(), "");
   }
   fc->GetPadSave()->Update();
   fc->GetPadSave()->Modified();
   gROOT->SetSelectedPad(psave);
   gROOT->GetSelectedPad()->Update();
   gROOT->GetSelectedPad()->Modified();
   fc->Modified();
   fc->ForceUpdate();
   gROOT->SetFromPopUp( kFALSE );
}

//______________________________________________________________________________
void TQCanvasMenu::Dialog(TObject* object, TMethod* method)
{
   // Create dialog object with OK and Cancel buttons. This dialog
   // prompts for the arguments of "method".

   if (!(object && method)) return;
   fDialog = new TQRootDialog(fParent,CreateDialogTitle(object, method),0,object ,method);
   fDialog->SetTCanvas(fc);
   // iterate through all arguments and create apropriate input-data objects:
   // inputlines, option menus...
   TMethodArg *argument = 0;
   TIter next(method->GetListOfMethodArgs());
   while ((argument = (TMethodArg *) next())) {
      char       *argname    = CreateArgumentTitle(argument);
      const char *type       = argument->GetTypeName();
      TDataType    *datatype   = gROOT->GetType(type);
      const char *charstar   = "char*";
      char        basictype [32];

      if (datatype) {
         strlcpy(basictype, datatype->GetTypeName(),32);
      }
      else {
         if (strncmp(type, "enum", 4) != 0)
         cout << "*** Warning in Dialog(): data type is not basic type, assuming (int)\n";
         strcpy(basictype, "int");
      }

      if (strchr(argname, '*')) {
         strcat(basictype, "*");
         type = charstar;
      }

      TDataMember *m = argument->GetDataMember();
      if (m && m->GetterMethod()) {
         char gettername[256] = "";
         strlcpy(gettername, m->GetterMethod()->GetMethodName(),256);
         m->GetterMethod()->Init(object->IsA(), gettername, "");
         // Get the current value and form it as a text:
         char val[256];
         if (!strncmp(basictype, "char*", 5)) {
            char *tdefval;
            m->GetterMethod()->Execute(object, "", &tdefval);
            strlcpy(val, tdefval, 256);
         }
         else if (!strncmp(basictype, "float", 5) ||
            !strncmp(basictype, "double", 6)) {
            Double_t ddefval = 0.0;
            m->GetterMethod()->Execute(object, "", ddefval);
            snprintf(val, 255, "%g", ddefval);
         }
         else if (!strncmp(basictype, "char", 4) ||
             !strncmp(basictype, "int", 3)  ||
             !strncmp(basictype, "long", 4) ||
             !strncmp(basictype, "short", 5)) {
            Long_t ldefval = 0L;
            m->GetterMethod()->Execute(object, "", ldefval);
            snprintf(val, 255, "%li", ldefval);
         }
         // Find out whether we have options ...
         TList *opt;
         if ((opt = m->GetOptions())) {
            cout << "*** Warning in Dialog(): option menu not yet implemented " << opt << endl;
            // should stop dialog
            return;
         }
         else {
            // we haven't got options - textfield ...
            fDialog->Add(argname, val, type);
         }
      }
      else {    // if m not found ...
         char val[256] = "";
         const char *tval = argument->GetDefault();
         if (tval) strlcpy(val, tval, 256);
         fDialog->Add(argname, val, type);
      }
   } //end while

   fDialog->Popup();
}
<commit_msg>Fix coverity #36613 Uninitialized pointer read<commit_after>// @(#)root/qtgsi:$Id$
// Author: Denis Bertini, M. Al-Turany  01/11/2000

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "qevent.h"
#include "qdialog.h"
#include "qpushbutton.h"
#include "qlabel.h"
#include "qpainter.h"
#if  (QT_VERSION > 0x039999) // Added by cholm@nbi.dk - for Qt 4
# include "qmenu.h"
# include "q3popupmenu.h"
typedef Q3PopupMenu QPopupMenu;
#else
# include "qpopupmenu.h"
#endif

#include "TQCanvasMenu.h"
#include "TClass.h"
#include "TROOT.h"
#include "TMethod.h"
#include "TMethodCall.h"
#include "TMethodArg.h"
#include "TCanvas.h"
#include "TDataType.h"
#include "TQRootDialog.h"

ClassImp(TQCanvasMenu)

//______________________________________________________________________________
TQCanvasMenu::TQCanvasMenu(QWidget* parent, TCanvas *canvas)
{
   // ctor, create the popup menu

   fc       = canvas;
   fPopup   = new QPopupMenu;
   fCurrObj = 0;
   fParent  = parent;
   fTabWin  = 0;
   fDialog  = 0;
   fMousePosX = fMousePosY = 0;
}

//______________________________________________________________________________
TQCanvasMenu::TQCanvasMenu(QWidget* parent, QWidget *tabWin, TCanvas *canvas)
{
   // ctor, create the popup menu

   fc       = canvas;
   fPopup   = new QPopupMenu;
   fParent  = parent;
   fTabWin  = tabWin;
   fCurrObj = 0;
   fDialog  = 0;
   fMousePosX = fMousePosY = 0;
}

//______________________________________________________________________________
TQCanvasMenu::~TQCanvasMenu()
{
   // dtor

   if (fPopup) delete fPopup;
}

//______________________________________________________________________________
char *TQCanvasMenu::CreateDialogTitle( TObject *object, TMethod *method )
{
   // Create title for dialog box retrieving argument values.

   static char methodTitle[128];

   if (object && method)
      snprintf(methodTitle, 127, "%s::%s", object->ClassName(), method->GetName());
   else
      *methodTitle = 0;
   return methodTitle;

}

//______________________________________________________________________________
char *TQCanvasMenu::CreateArgumentTitle(TMethodArg *argument)
{
   // Create string describing argument (for use in dialog box).

   static Char_t argTitle[128];
   if (argument) {
      snprintf(argTitle, 127, "(%s)  %s", argument->GetTitle(), argument->GetName());
      const char *arg_def = argument->GetDefault();
      if (arg_def && *arg_def) {
         strncat(argTitle, "  [default: ", 127 - strlen(argTitle));
         strncat(argTitle, arg_def, 127 - strlen(argTitle));
         strncat(argTitle, "]", 127 - strlen(argTitle));
      }
   }
   else
      *argTitle = 0;

   return argTitle;
}

//______________________________________________________________________________
void TQCanvasMenu::Popup(TObject *obj, double x, double y, QMouseEvent *e)
{
   // Perform the corresponding selected TObject  popup
   // in the position defined
   // by x, y coordinates (in user coordinate system).
   // @param obj (TObject*)
   // @param p (QPoint&)

   TClass *klass=obj->IsA();
   Int_t curId=-1;

   fCurrObj=obj;
   fPopup->clear();
   fMethods.Clear();

   QString buffer=klass->GetName();
   buffer+="::";
   buffer+=obj->GetName();
   fPopup->insertItem(buffer, this, SLOT( Execute(int) ), 0,curId); curId++;
   klass->GetMenuItems(&fMethods);
   fPopup->insertSeparator();
   TIter iter(&fMethods);
   TMethod *method=0;
   while ( (method = dynamic_cast<TMethod*>(iter())) != 0) {
      buffer=method->GetName();
      fPopup->insertItem(buffer, this, SLOT( Execute(int) ), 0,curId);
      curId++;
   }
   // hold the position where the mouse was clicked
   fMousePosX= x;
   fMousePosY= y;

   // let Qt decide how to draw the popup Menu otherwise we have a problem that
   // the visible rectangle can get outside the screen (M.T. 03.06.02)
   fPopup->popup(e->globalPos(), 0);

}

//______________________________________________________________________________
void TQCanvasMenu::Execute(int id)
{
   // Slot defined to execute a method from a selected TObject
   // using TObject::Execute() function.

   QString text="";

   TVirtualPad  *psave = gROOT->GetSelectedPad();
   TMethod *method=(TMethod *)fMethods.At(id);
   fc->HandleInput(kButton3Up,gPad->XtoAbsPixel(fMousePosX), gPad->YtoAbsPixel(fMousePosY) );
   if (  method->GetListOfMethodArgs()->First() ) {
      Dialog(fCurrObj,method);
   }
   else {
      gROOT->SetFromPopUp(kTRUE);
      fCurrObj->Execute((char *) method->GetName(), "");
   }
   fc->GetPadSave()->Update();
   fc->GetPadSave()->Modified();
   gROOT->SetSelectedPad(psave);
   gROOT->GetSelectedPad()->Update();
   gROOT->GetSelectedPad()->Modified();
   fc->Modified();
   fc->ForceUpdate();
   gROOT->SetFromPopUp( kFALSE );
}

//______________________________________________________________________________
void TQCanvasMenu::Dialog(TObject* object, TMethod* method)
{
   // Create dialog object with OK and Cancel buttons. This dialog
   // prompts for the arguments of "method".

   if (!(object && method)) return;
   fDialog = new TQRootDialog(fParent,CreateDialogTitle(object, method),0,object ,method);
   fDialog->SetTCanvas(fc);
   // iterate through all arguments and create apropriate input-data objects:
   // inputlines, option menus...
   TMethodArg *argument = 0;
   TIter next(method->GetListOfMethodArgs());
   while ((argument = (TMethodArg *) next())) {
      char       *argname    = CreateArgumentTitle(argument);
      const char *type       = argument->GetTypeName();
      TDataType    *datatype   = gROOT->GetType(type);
      const char *charstar   = "char*";
      char        basictype [32];

      if (datatype) {
         strlcpy(basictype, datatype->GetTypeName(),32);
      }
      else {
         if (strncmp(type, "enum", 4) != 0)
         cout << "*** Warning in Dialog(): data type is not basic type, assuming (int)\n";
         strcpy(basictype, "int");
      }

      if (strchr(argname, '*')) {
         strcat(basictype, "*");
         type = charstar;
      }

      TDataMember *m = argument->GetDataMember();
      if (m && m->GetterMethod()) {
         char gettername[256] = "";
         strlcpy(gettername, m->GetterMethod()->GetMethodName(),256);
         m->GetterMethod()->Init(object->IsA(), gettername, "");
         // Get the current value and form it as a text:
         char val[256];
         if (!strncmp(basictype, "char*", 5)) {
            char *tdefval = 0;
            m->GetterMethod()->Execute(object, "", &tdefval);
            if (tdefval && strlen(tdefval))
               strlcpy(val, tdefval, 256);
         }
         else if (!strncmp(basictype, "float", 5) ||
            !strncmp(basictype, "double", 6)) {
            Double_t ddefval = 0.0;
            m->GetterMethod()->Execute(object, "", ddefval);
            snprintf(val, 255, "%g", ddefval);
         }
         else if (!strncmp(basictype, "char", 4) ||
             !strncmp(basictype, "int", 3)  ||
             !strncmp(basictype, "long", 4) ||
             !strncmp(basictype, "short", 5)) {
            Long_t ldefval = 0L;
            m->GetterMethod()->Execute(object, "", ldefval);
            snprintf(val, 255, "%li", ldefval);
         }
         // Find out whether we have options ...
         TList *opt;
         if ((opt = m->GetOptions())) {
            cout << "*** Warning in Dialog(): option menu not yet implemented " << opt << endl;
            // should stop dialog
            return;
         }
         else {
            // we haven't got options - textfield ...
            fDialog->Add(argname, val, type);
         }
      }
      else {    // if m not found ...
         char val[256] = "";
         const char *tval = argument->GetDefault();
         if (tval) strlcpy(val, tval, 256);
         fDialog->Add(argname, val, type);
      }
   } //end while

   fDialog->Popup();
}
<|endoftext|>