<commit_before>//    Copyright (c) 2018 Will Wray https://keybase.io/willwray
//
//   Distributed under the Boost Software License, Version 1.0.
//          (http://www.boost.org/LICENSE_1_0.txt)

#pragma once

#include <cstring>
#include <string>
#include <string_view>
#include <typeinfo>
#include <type_traits>

#if __has_include(<cxxabi.h>)
#   include <cxxabi.h>
#   include <cstdlib>
#   include <memory>
#endif

constexpr bool CXXABI
{
#if __has_include(<cxxabi.h>)
    true
#endif
};

/*
  "type_name_rt.hpp": get type names at runtime (hence 'rt')
   ^^^^^^^^^^^^^^^^
   This header defines, in global scope (i.e. not namespace'd):
   (1) A function template type_name_str<T>() for extracting a type's name.
   (2) A variable template type_name_rt<T> initialized to the type's name.
      (also an incomplete class template IdT<T>, an implementation detail.)
   The template type parameter T is mapped to a readable name for the type.
   The work is done at runtime by what is the most standard current method;
   runtime type information (RTTI) and, on CXXABI, a demangle call
   (for compile-time alternatives see type_name_pt or type_name_ct).
   (1) type_name_str<T>()
                   Returns a std::string copy of the demangled typeid name.
                   On each call it does all the work, and cleans it all up
                   (i.e. it frees any demangle allocation once copied from).

   (2) type_name_rt<T>
                   A std::string_view global constant (a view into the
                   demangle buffer, on CXXABI, which is not ever free'd).
                   All work is done in static initialization, before main()

   Failure is signalled by an empty return value; ""
   (indicates a demangle failure as typeid is assumed fail-safe).
   Requirements:
       C++17 for string_view, constexpr-if, CTAD (unique_ptr) and __has_include
       RTTI, the compiler's runtime type information, must be enabled
   Dependencies: <string>,<string_view>,<type_traits> for std::conditional
      <typeinfo> (RTTI)
                 for typeid(T).name(), an implementation-defined name.
      <cxxabi.h> (on CXXABI platforms only - GCC, Clang, etc.)
                 for abi::__cxa_demangle(name,...)
                 to map typeid(T).name to a human readable name for T.
                 <cstdlib> for std::free, <memory> for std::unique_ptr
   E.g.
       int i;
       std::cout << type_name_rt<decltype(i)> << "\n^^^ tada!";
       --- stdout ---
       int
       ^^^ tada!
*/

// IdT<T> wraps T as template param so typeid can't decay ref or cv quals.
// An implementation detail; must be a 3-character id, any 3 chars will do.
template <typename T> struct IdT {};

namespace impl
{
// demangle<bool Free=false>( const char* name)
//
//  (1) On non-CXXABI returns name, regardless of the template parameter.
//      i.e. the function does nothing but return its parameter, a char*.
//
//  (2) On CXXABI the demangle ABI is called and the result is returned
//      with return type depending on the boolean template argument:
//    (a) char* by default (Free=false). Any demangle malloc is not free'd.
//    (b) unique_ptr<char> (Free=true) to RAII-free any malloc'd chars.
//
//     The input name should be a valid mangled name like typeid(T).name()
//     Null return value implies demangle fail (no malloc, free is harmless).
//
template <bool Free = false>
auto
demangle(char const* name) noexcept(!CXXABI)
{
  if constexpr (!CXXABI) {
      return name;         // NOP: assume already demangled if not on CXXABI
  } else {
    auto dmg = abi::__cxa_demangle(name, nullptr, nullptr, nullptr);
    if constexpr (Free)
        return std::unique_ptr<char, decltype(std::free)*>( dmg, std::free);
    else
        return dmg;
  }
}

template <bool Free>
using demangle_t = decltype(demangle<Free>(std::declval<char const*>()));

// prefix_len (constant): prefix length of demangled typeid(IdT<T>)
//   for different compilers (remove 4 chars "int>" from the length)
size_t prefix_len()
{
  static size_t const len = std::strlen(demangle<>(typeid(IdT<int>).name()))
                          - std::strlen("int>");
  return len;
}

// type_name_rt<T>()       Returns string, frees any malloc from ABI demangle
// type_name_rt<T,false>() Returns string_view, does not free demangle malloc
//
template <typename T, bool Free = true>
  // The typeid name is passed in as a (default) argument because
  // then the function body is independent of the template type arg T.
  // Compilers may emit one function, for all Ts, inlining typeid & demangle.
auto
type_name_rt( char const* tid = typeid(IdT<T>).name() ) noexcept(!CXXABI)
 ->
    std::conditional_t<Free, std::string,
                             std::string_view>
{
  if (auto dmg = demangle<Free>(tid))
  {
    size_t const p = prefix_len();
    return { &*dmg + p, std::strlen(&*dmg) - p - 1 };
  }
  return "";
}
} // namespace impl

// type_name_str<T>() Returns a std::string copy of the demangled typeid name.
//
template <typename T>
std::string
const type_name_str() { return impl::type_name_rt<T>(); }

// type_name_rt<T> Global constant; "The Demangle that Never Dangles"
//
template <typename T>
inline
std::string_view
const type_name_rt = impl::type_name_rt<T, false>();
<commit_msg>move typeid inside impl::type_name_rt, specialize for cvref<commit_after>//    Copyright (c) 2018 Will Wray https://keybase.io/willwray
//
//   Distributed under the Boost Software License, Version 1.0.
//          (http://www.boost.org/LICENSE_1_0.txt)

#pragma once

#include <cstring>
#include <string>
#include <string_view>
#include <typeinfo>
#include <type_traits>

#if __has_include(<cxxabi.h>)
#   include <cxxabi.h>
#   include <cstdlib>
#   include <memory>
#endif

constexpr bool CXXABI
{
#if __has_include(<cxxabi.h>)
    true
#endif
};

/*
  "type_name_rt.hpp": get type names at runtime (hence 'rt')
   ^^^^^^^^^^^^^^^^
   This header defines, in global scope (i.e. not namespace'd):
   (1) A function template type_name_str<T>() for extracting a type's name.
   (2) A variable template type_name_rt<T> initialized to the type's name.
      (also an incomplete class template IdT<T>, an implementation detail.)
   The template type parameter T is mapped to a readable name for the type.
   The work is done at runtime by what is the most standard current method;
   runtime type information (RTTI) and, on CXXABI, a demangle call
   (for compile-time alternatives see type_name_pt or type_name_ct).
   (1) type_name_str<T>()
                   Returns a std::string copy of the demangled typeid name.
                   On each call it does all the work, and cleans it all up
                   (i.e. it frees any demangle allocation once copied from).

   (2) type_name_rt<T>
                   A std::string_view global constant (a view into the
                   demangle buffer, on CXXABI, which is not ever free'd).
                   All work is done in static initialization, before main()

   Failure is signalled by an empty return value; ""
   (indicates a demangle failure as typeid is assumed fail-safe).
   Requirements:
       C++17 for string_view, constexpr-if, CTAD (unique_ptr) and __has_include
       RTTI, the compiler's runtime type information, must be enabled
   Dependencies: <string>,<string_view>,<type_traits> for std::conditional
      <typeinfo> (RTTI)
                 for typeid(T).name(), an implementation-defined name.
      <cxxabi.h> (on CXXABI platforms only - GCC, Clang, etc.)
                 for abi::__cxa_demangle(name,...)
                 to map typeid(T).name to a human readable name for T.
                 <cstdlib> for std::free, <memory> for std::unique_ptr
   E.g.
       int i;
       std::cout << type_name_rt<decltype(i)> << "\n^^^ tada!";
       --- stdout ---
       int
       ^^^ tada!
*/

// IdT<T> wraps T as template param so typeid can't decay ref or cv quals.
// An implementation detail; must be a 3-character id, any 3 chars will do.
template <typename T> struct IdT {};

namespace impl
{
// demangle<bool Free=false>( const char* name)
//
//  (1) On non-CXXABI returns name, regardless of the template parameter.
//      i.e. the function does nothing but return its parameter, a char*.
//
//  (2) On CXXABI the demangle ABI is called and the result is returned
//      with return type depending on the boolean template argument:
//    (a) char* by default (Free=false). Any demangle malloc is not free'd.
//    (b) unique_ptr<char> (Free=true) to RAII-free any malloc'd chars.
//
//     The input name should be a valid mangled name like typeid(T).name()
//     Null return value implies demangle fail (no malloc, free is harmless).
//
template <bool Free = false>
auto
demangle(char const* name) noexcept(!CXXABI)
{
  if constexpr (!CXXABI) {
      return name;         // NOP: assume already demangled if not on CXXABI
  } else {
    auto dmg = abi::__cxa_demangle(name, nullptr, nullptr, nullptr);
    if constexpr (Free)
        return std::unique_ptr<char, decltype(std::free)*>( dmg, std::free);
    else
        return dmg;
  }
}

// prefix_len (constant): prefix length of demangled typeid(IdT<T>)
//   for different compilers (remove 4 chars "int>" from the length)
size_t IdT_prefix_len()
{
  static size_t const len = std::strlen(demangle<>(typeid(IdT<int>).name()))
                          - std::strlen("int>");
  return len;
}

template <typename T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;

template <typename T>
inline constexpr bool is_cvref_v = !std::is_same_v<T,remove_cvref_t<T>>;

// type_name_rt<T>()       Returns string, frees any malloc from ABI demangle
// type_name_rt<T,false>() Returns string_view, does not free demangle malloc
//
template <typename T, bool Free = true, typename = void>
auto
type_name_rt() noexcept(!CXXABI) -> std::conditional_t<Free, std::string,
                                                             std::string_view>
{
  if constexpr (!is_cvref_v<T>)
  {
    if (auto dmg = demangle<Free>(typeid(T).name()))
    {
      return { &*dmg };
    }
  }
  else // wrap all cvref types for now - maybe only do functions and arrays
  {
    if (auto dmg = demangle<Free>(typeid(IdT<T>).name()))
    {
      size_t const p = IdT_prefix_len();
      return { &*dmg + p, std::strlen(&*dmg) - p - 1 };
    }
  }
  return "";
}
} // namespace impl

// type_name_str<T>() Returns a std::string copy of the demangled typeid name.
//
template <typename T>
std::string
const type_name_str() { return impl::type_name_rt<T>(); }

// type_name_rt<T> Global constant; "The Demangle that Never Dangles"
//
template <typename T>
inline
std::string_view
const type_name_rt = impl::type_name_rt<T, false>();
<|endoftext|>


<commit_before>#include "ui/nodes_view.h"

#include <QDebug>
#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QDragMoveEvent>
#include <QGraphicsLineItem>
#include <QMimeData>
#include <QTimeLine>

#include "core/registry.h"
#include "elements/package.h"
#include "nodes/node.h"
#include "ui/elements_list.h"
#include "ui/link_item.h"
#include "ui/package_view.h"

NodesView::NodesView(QGraphicsScene *const a_scene, PackageView *a_parent)
  : QGraphicsView{ a_scene, a_parent }
  , m_packageView{ a_parent }
{
  setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing |
                 QPainter::SmoothPixmapTransform);
  setDragMode(QGraphicsView::RubberBandDrag);
  setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  setResizeAnchor(QGraphicsView::NoAnchor);
  setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
  setObjectName("GraphicsView");

  setViewportUpdateMode(QGraphicsView::FullViewportUpdate);

  constexpr int32_t SIZE = 10000;
  constexpr int32_t SPACING = 10;
  QPen pen{ QColor(156, 156, 156, 32) };
  for (int32_t i = -SIZE; i < SIZE; i += SPACING) {
    QGraphicsLineItem *const horizontal{ new QGraphicsLineItem{ static_cast<qreal>(i), -SIZE, static_cast<qreal>(i), SIZE } };
    horizontal->setPen(pen);
    horizontal->setZValue(-100.0);
    a_scene->addItem(horizontal);

    QGraphicsLineItem *const vertical{ new QGraphicsLineItem{ -SIZE, static_cast<qreal>(i), SIZE, static_cast<qreal>(i) } };
    vertical->setPen(pen);
    vertical->setZValue(-100.0);
    a_scene->addItem(vertical);
  }

  setAcceptDrops(true);

}

NodesView::~NodesView() {}

void NodesView::dragEnterEvent(QDragEnterEvent *a_event)
{
  if (a_event->mimeData()->hasText()) {
    auto const pathString = a_event->mimeData()->text();
    auto const name = a_event->mimeData()->data("metadata/name");
    auto const icon = a_event->mimeData()->data("metadata/icon");
    auto const stringData = pathString.toLatin1();
    char const *const path{ stringData.data() };

    auto const dropPosition = mapToScene(a_event->pos());

    core::Registry &registry{ core::Registry::get() };

    assert(m_dragNode == nullptr);
    m_dragNode = registry.createNode(path);
    m_dragNode->setName(name);
    m_dragNode->setPath(pathString);
    m_dragNode->setIcon(icon);
    m_dragNode->setPos(dropPosition);
    scene()->addItem(m_dragNode);

    a_event->accept();
  } else
    QGraphicsView::dragEnterEvent(a_event);
}

void NodesView::dragLeaveEvent([[maybe_unused]] QDragLeaveEvent *a_event)
{
  scene()->removeItem(m_dragNode);
  delete m_dragNode;
  m_dragNode = nullptr;
}

void NodesView::dragMoveEvent(QDragMoveEvent *a_event)
{
  auto const dropPosition = mapToScene(a_event->pos());
  if (m_dragNode)
    m_dragNode->setPos(dropPosition);
  else if (m_dragLink) {
    QGraphicsView::dragMoveEvent(a_event);
    m_dragLink->setTo(mapToScene(a_event->pos()));
  }
}

void NodesView::dropEvent(QDropEvent *a_event)
{
  if (a_event->mimeData()->hasText()) {
    auto const pathString = a_event->mimeData()->text();
    auto const stringData = pathString.toLatin1();
    char const *const path{ stringData.data() };

    auto package = m_packageView->package();
    auto element = package->add(path);
    m_dragNode->setElement(element);
    m_dragNode->expand();
    m_dragNode = nullptr;
  }

  QGraphicsView::dropEvent(a_event);
}

void NodesView::keyReleaseEvent(QKeyEvent *a_event)
{
  qDebug() << a_event;

  auto const selected = scene()->selectedItems();
  for (auto &&item : selected) {
    if (item->type() == nodes::NODE_TYPE) {
      qDebug() << "Node:" << item;
    }
  }
}

void NodesView::wheelEvent(QWheelEvent *a_event)
{
  qDebug() << a_event;
  int32_t const numDegrees{ a_event->delta() / 8 };
  int32_t const numSteps{ numDegrees / 15 };

  m_scheduledScalings += numSteps;

  if (m_scheduledScalings * numSteps < 0) m_scheduledScalings = numSteps;

  QTimeLine *const animation{ new QTimeLine{ 350, this } };
  animation->setUpdateInterval(20);

  connect(animation, &QTimeLine::valueChanged, [&](qreal) {
    qreal const factor{ 1.0 + static_cast<qreal>(m_scheduledScalings) / 300.0 };
    QMatrix temp{ matrix() };
    temp.scale(factor, factor);
    if (temp.m11() >= 0.3 && temp.m11() < 3.0) scale(factor, factor);
  });
  connect(animation, &QTimeLine::finished, [&]() {
    if (m_scheduledScalings > 0)
      m_scheduledScalings--;
    else
      m_scheduledScalings++;
    if (sender()) sender()->deleteLater();
  });

  animation->start();
}

void NodesView::mouseMoveEvent(QMouseEvent *a_event)
{
  QGraphicsView::mouseMoveEvent(a_event);
}

void NodesView::setDragLink(LinkItem *a_link)
{
  m_dragLink = a_link;
}

void NodesView::acceptDragLink()
{
  m_dragLink = nullptr;
}

void NodesView::cancelDragLink()
{
  delete m_dragLink;
  m_dragLink = nullptr;
}
<commit_msg>Set drag mode & transformation anchor<commit_after>#include "ui/nodes_view.h"

#include <QDebug>
#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QDragMoveEvent>
#include <QGraphicsLineItem>
#include <QMimeData>
#include <QTimeLine>

#include "core/registry.h"
#include "elements/package.h"
#include "nodes/node.h"
#include "ui/elements_list.h"
#include "ui/link_item.h"
#include "ui/package_view.h"

NodesView::NodesView(QGraphicsScene *const a_scene, PackageView *a_parent)
  : QGraphicsView{ a_scene, a_parent }
  , m_packageView{ a_parent }
{
  setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing |
                 QPainter::SmoothPixmapTransform);
  setDragMode(QGraphicsView::ScrollHandDrag);
  setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  setResizeAnchor(QGraphicsView::NoAnchor);
  setTransformationAnchor(QGraphicsView::AnchorViewCenter);
  setObjectName("GraphicsView");

  setViewportUpdateMode(QGraphicsView::FullViewportUpdate);

  constexpr int32_t SIZE = 10000;
  constexpr int32_t SPACING = 10;
  QPen pen{ QColor(156, 156, 156, 32) };
  for (int32_t i = -SIZE; i < SIZE; i += SPACING) {
    QGraphicsLineItem *const horizontal{ new QGraphicsLineItem{ static_cast<qreal>(i), -SIZE, static_cast<qreal>(i), SIZE } };
    horizontal->setPen(pen);
    horizontal->setZValue(-100.0);
    a_scene->addItem(horizontal);

    QGraphicsLineItem *const vertical{ new QGraphicsLineItem{ -SIZE, static_cast<qreal>(i), SIZE, static_cast<qreal>(i) } };
    vertical->setPen(pen);
    vertical->setZValue(-100.0);
    a_scene->addItem(vertical);
  }

  setAcceptDrops(true);

}

NodesView::~NodesView() {}

void NodesView::dragEnterEvent(QDragEnterEvent *a_event)
{
  if (a_event->mimeData()->hasText()) {
    auto const pathString = a_event->mimeData()->text();
    auto const name = a_event->mimeData()->data("metadata/name");
    auto const icon = a_event->mimeData()->data("metadata/icon");
    auto const stringData = pathString.toLatin1();
    char const *const path{ stringData.data() };

    auto const dropPosition = mapToScene(a_event->pos());

    core::Registry &registry{ core::Registry::get() };

    assert(m_dragNode == nullptr);
    m_dragNode = registry.createNode(path);
    m_dragNode->setName(name);
    m_dragNode->setPath(pathString);
    m_dragNode->setIcon(icon);
    m_dragNode->setPos(dropPosition);
    scene()->addItem(m_dragNode);

    a_event->accept();
  } else
    QGraphicsView::dragEnterEvent(a_event);
}

void NodesView::dragLeaveEvent([[maybe_unused]] QDragLeaveEvent *a_event)
{
  scene()->removeItem(m_dragNode);
  delete m_dragNode;
  m_dragNode = nullptr;
}

void NodesView::dragMoveEvent(QDragMoveEvent *a_event)
{
  auto const dropPosition = mapToScene(a_event->pos());
  if (m_dragNode)
    m_dragNode->setPos(dropPosition);
  else if (m_dragLink) {
    QGraphicsView::dragMoveEvent(a_event);
    m_dragLink->setTo(mapToScene(a_event->pos()));
  }
}

void NodesView::dropEvent(QDropEvent *a_event)
{
  if (a_event->mimeData()->hasText()) {
    auto const pathString = a_event->mimeData()->text();
    auto const stringData = pathString.toLatin1();
    char const *const path{ stringData.data() };

    auto package = m_packageView->package();
    auto element = package->add(path);
    m_dragNode->setElement(element);
    m_dragNode->expand();
    m_dragNode = nullptr;
  }

  QGraphicsView::dropEvent(a_event);
}

void NodesView::keyReleaseEvent(QKeyEvent *a_event)
{
  qDebug() << a_event;

  auto const selected = scene()->selectedItems();
  for (auto &&item : selected) {
    if (item->type() == nodes::NODE_TYPE) {
      qDebug() << "Node:" << item;
    }
  }
}

void NodesView::wheelEvent(QWheelEvent *a_event)
{
  qDebug() << a_event;
  int32_t const numDegrees{ a_event->delta() / 8 };
  int32_t const numSteps{ numDegrees / 15 };

  m_scheduledScalings += numSteps;

  if (m_scheduledScalings * numSteps < 0) m_scheduledScalings = numSteps;

  QTimeLine *const animation{ new QTimeLine{ 350, this } };
  animation->setUpdateInterval(20);

  connect(animation, &QTimeLine::valueChanged, [&](qreal) {
    qreal const factor{ 1.0 + static_cast<qreal>(m_scheduledScalings) / 300.0 };
    QMatrix temp{ matrix() };
    temp.scale(factor, factor);
    if (temp.m11() >= 0.3 && temp.m11() < 3.0) scale(factor, factor);
  });
  connect(animation, &QTimeLine::finished, [&]() {
    if (m_scheduledScalings > 0)
      m_scheduledScalings--;
    else
      m_scheduledScalings++;
    if (sender()) sender()->deleteLater();
  });

  animation->start();
}

void NodesView::mouseMoveEvent(QMouseEvent *a_event)
{
  QGraphicsView::mouseMoveEvent(a_event);
}

void NodesView::setDragLink(LinkItem *a_link)
{
  m_dragLink = a_link;
}

void NodesView::acceptDragLink()
{
  m_dragLink = nullptr;
}

void NodesView::cancelDragLink()
{
  delete m_dragLink;
  m_dragLink = nullptr;
}
<|endoftext|>


<commit_before>// Filename: extractor.cxx
// Created by:  mike (09Jan97)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "extractor.h"
#include "config_downloader.h"

#include "filename.h"
#include "error_utils.h"

////////////////////////////////////////////////////////////////////
//     Function: Extractor::Constructor
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
Extractor::
Extractor() {
  _initiated = false;
  _multifile = new Multifile;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::Destructor
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
Extractor::
~Extractor() {
  reset();
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::set_multifile
//       Access: Published
//  Description: Specifies the filename of the Multifile that the
//               Extractor will read.  Returns true on success, false
//               if the mulifile name is invalid.
////////////////////////////////////////////////////////////////////
bool Extractor::
set_multifile(const Filename &multifile_name) {
  reset();
  _multifile_name = multifile_name;
  return _multifile->open_read(multifile_name);
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::set_extract_dir
//       Access: Published
//  Description: Specifies the directory into which all extracted
//               subfiles will be written.  Relative paths of subfiles
//               within the Multifile will be written as relative
//               paths to this directory.
////////////////////////////////////////////////////////////////////
void Extractor::
set_extract_dir(const Filename &extract_dir) {
  _extract_dir = extract_dir;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::reset
//       Access: Published
//  Description: Interrupts the Extractor in the middle of its
//               business and makes it ready to accept a new list of
//               subfiles to extract.
////////////////////////////////////////////////////////////////////
void Extractor::
reset() {
  if (_initiated) {
    if (_read != (istream *)NULL) {
      delete _read;
      _read = (istream *)NULL;
    }
    _write.close();
    _initiated = false;
  }

  _requests.clear();
  _requests_total_length = 0;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::request_subfile
//       Access: Published
//  Description: Requests a particular subfile to be extracted when
//               step() or run() is called.  Returns true if the
//               subfile exists, false otherwise.
////////////////////////////////////////////////////////////////////
bool Extractor::
request_subfile(const Filename &subfile_name) {
  int index = _multifile->find_subfile(subfile_name);
  if (index < 0) {
    return false;
  }
  _requests.push_back(index);
  _requests_total_length += _multifile->get_subfile_length(index);
  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::request_all_subfiles
//       Access: Published
//  Description: Requests all subfiles in the Multifile to be
//               extracted.  Returns the number requested.
////////////////////////////////////////////////////////////////////
int Extractor::
request_all_subfiles() {
  _requests.clear();
  _requests_total_length = 0;
  int num_subfiles = _multifile->get_num_subfiles();
  for (int i = 0; i < num_subfiles; i++) {
    _requests.push_back(i);
    _requests_total_length += _multifile->get_subfile_length(i);
  }
  return num_subfiles;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::step
//       Access: Published
//  Description: After all of the requests have been made via
//               request_file() or request_all_subfiles(), call step()
//               repeatedly until it stops returning EU_ok.
//
//               step() extracts the next small unit of data from the
//               Multifile.  Returns EU_ok if progress is continuing,
//               EU_error_abort if there is a problem, or EU_success
//               when the last piece has been extracted.
//
//               Also see run().
////////////////////////////////////////////////////////////////////
int Extractor::
step() {
  if (!_initiated) {
    _request_index = 0;
    _subfile_index = 0;
    _subfile_pos = 0;
    _subfile_length = 0;
    _total_bytes_extracted = 0;
    _read = (istream *)NULL;
    _initiated = true;
  }

  TrueClock *clock = TrueClock::get_global_ptr();
  double now = clock->get_short_time();
  double finish = now + extractor_step_time;

  do {
    if (_read == (istream *)NULL) {
      // Time to open the next subfile.
      if (_request_index >= (int)_requests.size()) {
        // All done!
        if (downloader_cat.is_debug()) {
          downloader_cat.debug()
            << "Finished extracting.\n";
        }
        reset();
        return EU_success;
      }

      _subfile_index = _requests[_request_index];
      _subfile_filename = Filename(_extract_dir,
                                   _multifile->get_subfile_name(_subfile_index));

      if (downloader_cat.is_debug()) {
        downloader_cat.debug()
          << "Extracting " << _subfile_filename << ".\n";
      }

      _subfile_filename.set_binary();
      _subfile_filename.make_dir();
      if (!_subfile_filename.open_write(_write, true)) {
        downloader_cat.error()
          << "Unable to write to " << _subfile_filename << ".\n";
        reset();
        return EU_error_abort;
      }

      _subfile_length = _multifile->get_subfile_length(_subfile_index);
      _subfile_pos = 0;
      _read = _multifile->open_read_subfile(_subfile_index);
      if (_read == (istream *)NULL) {
        downloader_cat.error()
          << "Unable to read subfile "
          << _multifile->get_subfile_name(_subfile_index) << ".\n";
        reset();
        return EU_error_abort;
      }

    } else if (_subfile_pos >= _subfile_length) {
      // Time to close this subfile.

      if (downloader_cat.is_debug()) {
        downloader_cat.debug()
          << "Finished current subfile.\n";
      }
      delete _read;
      _read = (istream *)NULL;
      _write.close();
      _request_index++;

    } else {
      // Read a number of bytes from the subfile and write them to the
      // output.
      static const size_t buffer_size = 1024;
      char buffer[buffer_size];

      size_t max_bytes = min(buffer_size, _subfile_length - _subfile_pos);
      _read->read(buffer, max_bytes);
      size_t count = _read->gcount();
      while (count != 0) {
        if (downloader_cat.is_spam()) {
          downloader_cat.spam()
            << " . . . read " << count << " bytes.\n";
        }
        _write.write(buffer, count);
        if (!_write) {
          downloader_cat.error()
            << "Error writing to " << _subfile_filename << ".\n";
          reset();
          return EU_error_abort;
        }

        _subfile_pos += count;
        _total_bytes_extracted += count;

        now = clock->get_short_time();
        if (now >= finish) {
          // That's enough for now.
          return EU_ok;
        }

        max_bytes = min(buffer_size, _subfile_length - _subfile_pos);
        _read->read(buffer, max_bytes);
        count = _read->gcount();
      }

      if (max_bytes != 0) {
        downloader_cat.error()
          << "Unexpected EOF on multifile " << _multifile_name << ".\n";
        reset();
        return EU_error_abort;
      }
    }

    now = clock->get_short_time();
  } while (now < finish);

  // That's enough for now.
  return EU_ok;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::get_progress
//       Access: Public
//  Description: Returns the fraction of the Multifile extracted so
//               far.
////////////////////////////////////////////////////////////////////
float Extractor::
get_progress() const {
  if (!_initiated) {
    return 0.0f;
  }
  if (_requests_total_length == 0) {
    return 1.0f;
  }

  return (float)_total_bytes_extracted / (float)_requests_total_length;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::run
//       Access: Published
//  Description: A convenience function to extract the Multifile all
//               at once, when you don't care about doing it in the
//               background.
//
//               First, call request_file() or request_all_files() to
//               specify the files you would like to extract, then
//               call run() to do the extraction.  Also see step() for
//               when you would like the extraction to happen as a
//               background task.
////////////////////////////////////////////////////////////////////
bool Extractor::
run() {
  while (true) {
    int ret = step();
    if (ret == EU_success) {
      return true;
    }
    if (ret < 0) {
      return false;
    }
  }
}
<commit_msg>add missing include<commit_after>// Filename: extractor.cxx
// Created by:  mike (09Jan97)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "extractor.h"
#include "config_downloader.h"
#include "trueClock.h"
#include "filename.h"
#include "error_utils.h"

////////////////////////////////////////////////////////////////////
//     Function: Extractor::Constructor
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
Extractor::
Extractor() {
  _initiated = false;
  _multifile = new Multifile;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::Destructor
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
Extractor::
~Extractor() {
  reset();
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::set_multifile
//       Access: Published
//  Description: Specifies the filename of the Multifile that the
//               Extractor will read.  Returns true on success, false
//               if the mulifile name is invalid.
////////////////////////////////////////////////////////////////////
bool Extractor::
set_multifile(const Filename &multifile_name) {
  reset();
  _multifile_name = multifile_name;
  return _multifile->open_read(multifile_name);
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::set_extract_dir
//       Access: Published
//  Description: Specifies the directory into which all extracted
//               subfiles will be written.  Relative paths of subfiles
//               within the Multifile will be written as relative
//               paths to this directory.
////////////////////////////////////////////////////////////////////
void Extractor::
set_extract_dir(const Filename &extract_dir) {
  _extract_dir = extract_dir;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::reset
//       Access: Published
//  Description: Interrupts the Extractor in the middle of its
//               business and makes it ready to accept a new list of
//               subfiles to extract.
////////////////////////////////////////////////////////////////////
void Extractor::
reset() {
  if (_initiated) {
    if (_read != (istream *)NULL) {
      delete _read;
      _read = (istream *)NULL;
    }
    _write.close();
    _initiated = false;
  }

  _requests.clear();
  _requests_total_length = 0;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::request_subfile
//       Access: Published
//  Description: Requests a particular subfile to be extracted when
//               step() or run() is called.  Returns true if the
//               subfile exists, false otherwise.
////////////////////////////////////////////////////////////////////
bool Extractor::
request_subfile(const Filename &subfile_name) {
  int index = _multifile->find_subfile(subfile_name);
  if (index < 0) {
    return false;
  }
  _requests.push_back(index);
  _requests_total_length += _multifile->get_subfile_length(index);
  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::request_all_subfiles
//       Access: Published
//  Description: Requests all subfiles in the Multifile to be
//               extracted.  Returns the number requested.
////////////////////////////////////////////////////////////////////
int Extractor::
request_all_subfiles() {
  _requests.clear();
  _requests_total_length = 0;
  int num_subfiles = _multifile->get_num_subfiles();
  for (int i = 0; i < num_subfiles; i++) {
    _requests.push_back(i);
    _requests_total_length += _multifile->get_subfile_length(i);
  }
  return num_subfiles;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::step
//       Access: Published
//  Description: After all of the requests have been made via
//               request_file() or request_all_subfiles(), call step()
//               repeatedly until it stops returning EU_ok.
//
//               step() extracts the next small unit of data from the
//               Multifile.  Returns EU_ok if progress is continuing,
//               EU_error_abort if there is a problem, or EU_success
//               when the last piece has been extracted.
//
//               Also see run().
////////////////////////////////////////////////////////////////////
int Extractor::
step() {
  if (!_initiated) {
    _request_index = 0;
    _subfile_index = 0;
    _subfile_pos = 0;
    _subfile_length = 0;
    _total_bytes_extracted = 0;
    _read = (istream *)NULL;
    _initiated = true;
  }

  TrueClock *clock = TrueClock::get_global_ptr();
  double now = clock->get_short_time();
  double finish = now + extractor_step_time;

  do {
    if (_read == (istream *)NULL) {
      // Time to open the next subfile.
      if (_request_index >= (int)_requests.size()) {
        // All done!
        if (downloader_cat.is_debug()) {
          downloader_cat.debug()
            << "Finished extracting.\n";
        }
        reset();
        return EU_success;
      }

      _subfile_index = _requests[_request_index];
      _subfile_filename = Filename(_extract_dir,
                                   _multifile->get_subfile_name(_subfile_index));

      if (downloader_cat.is_debug()) {
        downloader_cat.debug()
          << "Extracting " << _subfile_filename << ".\n";
      }

      _subfile_filename.set_binary();
      _subfile_filename.make_dir();
      if (!_subfile_filename.open_write(_write, true)) {
        downloader_cat.error()
          << "Unable to write to " << _subfile_filename << ".\n";
        reset();
        return EU_error_abort;
      }

      _subfile_length = _multifile->get_subfile_length(_subfile_index);
      _subfile_pos = 0;
      _read = _multifile->open_read_subfile(_subfile_index);
      if (_read == (istream *)NULL) {
        downloader_cat.error()
          << "Unable to read subfile "
          << _multifile->get_subfile_name(_subfile_index) << ".\n";
        reset();
        return EU_error_abort;
      }

    } else if (_subfile_pos >= _subfile_length) {
      // Time to close this subfile.

      if (downloader_cat.is_debug()) {
        downloader_cat.debug()
          << "Finished current subfile.\n";
      }
      delete _read;
      _read = (istream *)NULL;
      _write.close();
      _request_index++;

    } else {
      // Read a number of bytes from the subfile and write them to the
      // output.
      static const size_t buffer_size = 1024;
      char buffer[buffer_size];

      size_t max_bytes = min(buffer_size, _subfile_length - _subfile_pos);
      _read->read(buffer, max_bytes);
      size_t count = _read->gcount();
      while (count != 0) {
        if (downloader_cat.is_spam()) {
          downloader_cat.spam()
            << " . . . read " << count << " bytes.\n";
        }
        _write.write(buffer, count);
        if (!_write) {
          downloader_cat.error()
            << "Error writing to " << _subfile_filename << ".\n";
          reset();
          return EU_error_abort;
        }

        _subfile_pos += count;
        _total_bytes_extracted += count;

        now = clock->get_short_time();
        if (now >= finish) {
          // That's enough for now.
          return EU_ok;
        }

        max_bytes = min(buffer_size, _subfile_length - _subfile_pos);
        _read->read(buffer, max_bytes);
        count = _read->gcount();
      }

      if (max_bytes != 0) {
        downloader_cat.error()
          << "Unexpected EOF on multifile " << _multifile_name << ".\n";
        reset();
        return EU_error_abort;
      }
    }

    now = clock->get_short_time();
  } while (now < finish);

  // That's enough for now.
  return EU_ok;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::get_progress
//       Access: Public
//  Description: Returns the fraction of the Multifile extracted so
//               far.
////////////////////////////////////////////////////////////////////
float Extractor::
get_progress() const {
  if (!_initiated) {
    return 0.0f;
  }
  if (_requests_total_length == 0) {
    return 1.0f;
  }

  return (float)_total_bytes_extracted / (float)_requests_total_length;
}

////////////////////////////////////////////////////////////////////
//     Function: Extractor::run
//       Access: Published
//  Description: A convenience function to extract the Multifile all
//               at once, when you don't care about doing it in the
//               background.
//
//               First, call request_file() or request_all_files() to
//               specify the files you would like to extract, then
//               call run() to do the extraction.  Also see step() for
//               when you would like the extraction to happen as a
//               background task.
////////////////////////////////////////////////////////////////////
bool Extractor::
run() {
  while (true) {
    int ret = step();
    if (ret == EU_success) {
      return true;
    }
    if (ret < 0) {
      return false;
    }
  }
}
<|endoftext|>


<commit_before>// Filename: config_dxgsg9.cxx
// Created by:  drose (06Oct99)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "config_dxgsg9.h"
#include "dxGraphicsStateGuardian9.h"
#include "dxTextureContext9.h"
#include "dxVertexBufferContext9.h"
#include "dxIndexBufferContext9.h"
#include "dxGeomMunger9.h"
#include "graphicsPipeSelection.h"
#include "wdxGraphicsWindow9.h"
#include "wdxGraphicsPipe9.h"
#include "pandaSystem.h"

#include "dconfig.h"

Configure(config_dxgsg9);
NotifyCategoryDef(dxgsg9, ":display:gsg");
NotifyCategoryDef(wdxdisplay9, "display");

// Configure this variable true to cause the DXGSG to show each
// transform space it renders by drawing a little unit axis.  This
// cannot be enabled when the player is compiled in NDEBUG mode.
ConfigVariableBool dx_show_transforms
("dx-show-transforms", false);

// Set Level of MultiSampling to be used, if HW supports it.  Valid values are 2-16.
ConfigVariableInt dx_multisample_antialiasing_level
("dx-multisample-antialiasing-level", 0);

// if true, if card only supports per-vertex fog, it will be treated as no-HW fog capability
ConfigVariableBool dx_no_vertex_fog
("dx-no-vertex-fog", false);

// if true, overwrite cursor bitmap tip with "D3D" to distinguish it from GDI cursor
ConfigVariableBool dx_show_cursor_watermark
("dx-show-cursor-watermark",
#ifdef _DEBUG
    true
#else
    false
#endif
    );

// if true, triangle filter will be used to generate mipmap levels instead of default box filter
ConfigVariableBool dx_use_triangle_mipgen_filter
("dx-use-triangle-mipgen-filter", false);

ConfigVariableBool dx_broken_max_index
("dx-broken-max-index", false,
 PRC_DESC("Configure this true if you have a buggy graphics driver that "
          "doesn't correctly implement the third parameter, NumVertices, "
          "of DrawIndexedPrimitive().  In particular, the NVIDIA Quadro "
          "driver version 6.14.10.7184 seems to treat this as a maximum "
          "vertex index, rather than a delta between the maximum and "
          "minimum vertex index.  Turn this on if you are seeing stray "
          "triangles, or you are not seeing all of your triangles.  Enabling "
          "this should work around this bug, at the cost of some additional "
          "rendering overhead on the GPU."));

#ifndef NDEBUG
// debugging flag
// values are same as D3DCULL enumtype, 0 - no force, 1 - force none, 2 - force CW, 3 - force CCW
ConfigVariableInt dx_force_backface_culling
("dx-force-backface-culling", 0);
#endif

ConfigVariableBool dx_mipmap_everything
("dx-mipmap-everything", false);
ConfigVariableBool dx_ignore_mipmaps
("dx-ignore-mipmaps", false);

// if this is set, more accurate but more expensive fog computations are performed
ConfigVariableBool dx_use_rangebased_fog
("dx-use-rangebased-fog", false);
ConfigVariableBool dx_force_16bpptextures
("dx-force-16bpptextures", false);
ConfigVariableBool dx_no_dithering
("dx-no-dithering", false);
ConfigVariableBool dx_force_16bpp_zbuffer
("dx-force-16bpp-zbuffer", false);
ConfigVariableBool dx_do_vidmemsize_check
("do-vidmemsize-check", true);
// Setting this true theoretically hinders render performance, because
// it forces the FPU to go through some extra work to clean itself up
// after rendering a frame, but the performance cost seems to be
// small.  On the other hand, setting it false can force the
// application to run in single-precision arithmetic mode, even if
// it believes it is using double-precision variables.
ConfigVariableBool dx_preserve_fpu_state
("dx-preserve-fpu-state", true);

// if true, override win-width/height and use driver vidmem info to
// pick what will be a fullscreen window size close to the best perf
// capability of card, based on a heuristic
ConfigVariableBool dx_pick_best_screenres
("pick-best-screenres", false);

ConfigVariableInt dx_preferred_device_id
("dx-preferred-device-id", -1);

#ifdef _DEBUG
ConfigVariableDouble dx_global_miplevel_bias
("dx-global-miplevel-bias", 0.0);
ConfigVariableBool dx_debug_view_mipmaps
("dx-debug-view-mipmaps", false);
#endif

ConfigVariableBool dx_force_anisotropic_filtering
("dx-force-anisotropic-filtering", false);

// set 'retained-mode #t' and this to have prepare_geom concatenate all tristrips within a geom
// together using degenerate tris
ConfigVariableBool link_tristrips
("link-tristrips", false);

// true = use DirectX management of video memory
// false = see dx_lru_management config variable below
ConfigVariableBool dx_management
("dx-management", false);

// valid only if dx_management == false
// true = enable LRU management of video memory
// false = no video memory management
ConfigVariableBool dx_lru_management
("dx-lru-management", true);

// number of LRU pages to pre-allocate
// if the maximum number of pages is used up,
// then LRU pages will be dynamically allocated/freed
ConfigVariableInt dx_lru_maximum_pages
("dx-lru-maximum-pages", 20000);

// the amount of video memory the LRU will try not to use
// this will allow DirectX some space in case of memory fragmentation, ...
// this does not apply if dx_lru_minimum_memory_requirement is not met
ConfigVariableInt dx_lru_free_memory_requirement
("dx-lru-free-memory-requirement", 5000000);

// this is like the minimum recommended amount of video memory
ConfigVariableInt dx_lru_minimum_memory_requirement
("dx-lru-minimum-memory-requirement", 64000000);

// used to cap the amount of video memory used
// 0 = use all available DirectX video memory
ConfigVariableInt dx_lru_maximum_memory_requirement
("dx-lru-maximum-memory-requirement", 128000000);

// the number of LRU pages the LRU will update per frame
// do not set this too high or it will degrade performance
ConfigVariableInt dx_lru_maximum_page_updates_per_frame
("dx-lru-maximum-page-updates-per-frame", 10);

// lru debug on/off
ConfigVariableBool dx_lru_debug
("dx-lru-debug", false);

// valid only if dx_lru_debug == true && notify-level-dxgsg9 == debug
// number of frames to wait until printing out the LRU status
ConfigVariableInt dx_lru_debug_frames_til_output
("dx-lru-debug-frames-til-output", 500);

ConfigureFn(config_dxgsg9) {
  init_libdxgsg9();
}

////////////////////////////////////////////////////////////////////
//     Function: init_libdxgsg
//  Description: Initializes the library.  This must be called at
//               least once before any of the functions or classes in
//               this library can be used.  Normally it will be
//               called by the static initializers and need not be
//               called explicitly, but special cases exist.
////////////////////////////////////////////////////////////////////
void
init_libdxgsg9() {
  static bool initialized = false;
  if (initialized) {
    return;
  }
  initialized = true;

  DXGraphicsStateGuardian9::init_type();
  DXTextureContext9::init_type();
  DXVertexBufferContext9::init_type();
  DXIndexBufferContext9::init_type();
  DXGeomMunger9::init_type();

  wdxGraphicsPipe9::init_type();
  wdxGraphicsWindow9::init_type();

  GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
  selection->add_pipe_type(wdxGraphicsPipe9::get_class_type(),
                           wdxGraphicsPipe9::pipe_constructor);

  PandaSystem *ps = PandaSystem::get_global_ptr();
  ps->add_system("DirectX9");
}
<commit_msg>set dx-management 1 as default add dx-use-dynamic-textures config option<commit_after>// Filename: config_dxgsg9.cxx
// Created by:  drose (06Oct99)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "config_dxgsg9.h"
#include "dxGraphicsStateGuardian9.h"
#include "dxTextureContext9.h"
#include "dxVertexBufferContext9.h"
#include "dxIndexBufferContext9.h"
#include "dxGeomMunger9.h"
#include "graphicsPipeSelection.h"
#include "wdxGraphicsWindow9.h"
#include "wdxGraphicsPipe9.h"
#include "pandaSystem.h"

#include "dconfig.h"

Configure(config_dxgsg9);
NotifyCategoryDef(dxgsg9, ":display:gsg");
NotifyCategoryDef(wdxdisplay9, "display");

// Configure this variable true to cause the DXGSG to show each
// transform space it renders by drawing a little unit axis.  This
// cannot be enabled when the player is compiled in NDEBUG mode.
ConfigVariableBool dx_show_transforms
("dx-show-transforms", false);

// Set Level of MultiSampling to be used, if HW supports it.  Valid values are 2-16.
ConfigVariableInt dx_multisample_antialiasing_level
("dx-multisample-antialiasing-level", 0);

// if true, if card only supports per-vertex fog, it will be treated as no-HW fog capability
ConfigVariableBool dx_no_vertex_fog
("dx-no-vertex-fog", false);

// if true, overwrite cursor bitmap tip with "D3D" to distinguish it from GDI cursor
ConfigVariableBool dx_show_cursor_watermark
("dx-show-cursor-watermark",
#ifdef _DEBUG
    true
#else
    false
#endif
    );

// if true, triangle filter will be used to generate mipmap levels instead of default box filter
ConfigVariableBool dx_use_triangle_mipgen_filter
("dx-use-triangle-mipgen-filter", false);

ConfigVariableBool dx_broken_max_index
("dx-broken-max-index", false,
 PRC_DESC("Configure this true if you have a buggy graphics driver that "
          "doesn't correctly implement the third parameter, NumVertices, "
          "of DrawIndexedPrimitive().  In particular, the NVIDIA Quadro "
          "driver version 6.14.10.7184 seems to treat this as a maximum "
          "vertex index, rather than a delta between the maximum and "
          "minimum vertex index.  Turn this on if you are seeing stray "
          "triangles, or you are not seeing all of your triangles.  Enabling "
          "this should work around this bug, at the cost of some additional "
          "rendering overhead on the GPU."));

#ifndef NDEBUG
// debugging flag
// values are same as D3DCULL enumtype, 0 - no force, 1 - force none, 2 - force CW, 3 - force CCW
ConfigVariableInt dx_force_backface_culling
("dx-force-backface-culling", 0);
#endif

ConfigVariableBool dx_mipmap_everything
("dx-mipmap-everything", false);
ConfigVariableBool dx_ignore_mipmaps
("dx-ignore-mipmaps", false);

// if this is set, more accurate but more expensive fog computations are performed
ConfigVariableBool dx_use_rangebased_fog
("dx-use-rangebased-fog", false);
ConfigVariableBool dx_force_16bpptextures
("dx-force-16bpptextures", false);
ConfigVariableBool dx_no_dithering
("dx-no-dithering", false);
ConfigVariableBool dx_force_16bpp_zbuffer
("dx-force-16bpp-zbuffer", false);
ConfigVariableBool dx_do_vidmemsize_check
("do-vidmemsize-check", true);
// Setting this true theoretically hinders render performance, because
// it forces the FPU to go through some extra work to clean itself up
// after rendering a frame, but the performance cost seems to be
// small.  On the other hand, setting it false can force the
// application to run in single-precision arithmetic mode, even if
// it believes it is using double-precision variables.
ConfigVariableBool dx_preserve_fpu_state
("dx-preserve-fpu-state", true);

// if true, override win-width/height and use driver vidmem info to
// pick what will be a fullscreen window size close to the best perf
// capability of card, based on a heuristic
ConfigVariableBool dx_pick_best_screenres
("pick-best-screenres", false);

ConfigVariableInt dx_preferred_device_id
("dx-preferred-device-id", -1);

#ifdef _DEBUG
ConfigVariableDouble dx_global_miplevel_bias
("dx-global-miplevel-bias", 0.0);
ConfigVariableBool dx_debug_view_mipmaps
("dx-debug-view-mipmaps", false);
#endif

ConfigVariableBool dx_force_anisotropic_filtering
("dx-force-anisotropic-filtering", false);

// set 'retained-mode #t' and this to have prepare_geom concatenate all tristrips within a geom
// together using degenerate tris
ConfigVariableBool link_tristrips
("link-tristrips", false);

// true = use DirectX management of video memory
// false = see dx_lru_management config variable below
ConfigVariableBool dx_management
("dx-management", true);

// valid only if dx_management == false
// true = enable LRU management of video memory
// false = no video memory management
ConfigVariableBool dx_lru_management
("dx-lru-management", true);

// number of LRU pages to pre-allocate
// if the maximum number of pages is used up,
// then LRU pages will be dynamically allocated/freed
ConfigVariableInt dx_lru_maximum_pages
("dx-lru-maximum-pages", 20000);

// the amount of video memory the LRU will try not to use
// this will allow DirectX some space in case of memory fragmentation, ...
// this does not apply if dx_lru_minimum_memory_requirement is not met
ConfigVariableInt dx_lru_free_memory_requirement
("dx-lru-free-memory-requirement", 5000000);

// this is like the minimum recommended amount of video memory
ConfigVariableInt dx_lru_minimum_memory_requirement
("dx-lru-minimum-memory-requirement", 64000000);

// used to cap the amount of video memory used
// 0 = use all available DirectX video memory
ConfigVariableInt dx_lru_maximum_memory_requirement
("dx-lru-maximum-memory-requirement", 128000000);

// the number of LRU pages the LRU will update per frame
// do not set this too high or it will degrade performance
ConfigVariableInt dx_lru_maximum_page_updates_per_frame
("dx-lru-maximum-page-updates-per-frame", 10);

// lru debug on/off
ConfigVariableBool dx_lru_debug
("dx-lru-debug", false);

// valid only if dx_lru_debug == true && notify-level-dxgsg9 == debug
// number of frames to wait until printing out the LRU status
ConfigVariableInt dx_lru_debug_frames_til_output
("dx-lru-debug-frames-til-output", 500);

ConfigVariableBool dx_use_dynamic_textures
("dx-use-dynamic-textures", true);

ConfigureFn(config_dxgsg9) {
  init_libdxgsg9();
}

////////////////////////////////////////////////////////////////////
//     Function: init_libdxgsg
//  Description: Initializes the library.  This must be called at
//               least once before any of the functions or classes in
//               this library can be used.  Normally it will be
//               called by the static initializers and need not be
//               called explicitly, but special cases exist.
////////////////////////////////////////////////////////////////////
void
init_libdxgsg9() {
  static bool initialized = false;
  if (initialized) {
    return;
  }
  initialized = true;

  DXGraphicsStateGuardian9::init_type();
  DXTextureContext9::init_type();
  DXVertexBufferContext9::init_type();
  DXIndexBufferContext9::init_type();
  DXGeomMunger9::init_type();

  wdxGraphicsPipe9::init_type();
  wdxGraphicsWindow9::init_type();

  GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
  selection->add_pipe_type(wdxGraphicsPipe9::get_class_type(),
                           wdxGraphicsPipe9::pipe_constructor);

  PandaSystem *ps = PandaSystem::get_global_ptr();
  ps->add_system("DirectX9");
}
<|endoftext|>


<commit_before>// Filename: config_grutil.cxx
// Created by:  drose (24May00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "config_grutil.h"
#include "frameRateMeter.h"
#include "openCVTexture.h"
#include "pandaSystem.h"
#include "texturePool.h"

#include "dconfig.h"

Configure(config_grutil);
NotifyCategoryDef(grutil, "");

ConfigureFn(config_grutil) {
  init_libgrutil();
}

ConfigVariableDouble frame_rate_meter_update_interval
("frame-rate-meter-update-interval", 1.5);

ConfigVariableString frame_rate_meter_text_pattern
("frame-rate-meter-text-pattern", "%0.1f fps");

ConfigVariableInt frame_rate_meter_layer_sort
("frame-rate-meter-layer-sort", 1000);

ConfigVariableDouble frame_rate_meter_scale
("frame-rate-meter-scale", 0.05);

ConfigVariableDouble frame_rate_meter_side_margins
("frame-rate-meter-side-margins", 0.5);

////////////////////////////////////////////////////////////////////
//     Function: init_libgrutil
//  Description: Initializes the library.  This must be called at
//               least once before any of the functions or classes in
//               this library can be used.  Normally it will be
//               called by the static initializers and need not be
//               called explicitly, but special cases exist.
////////////////////////////////////////////////////////////////////
void
init_libgrutil() {
  static bool initialized = false;
  if (initialized) {
    return;
  }
  initialized = true;

  FrameRateMeter::init_type();

#ifdef HAVE_OPENCV
  OpenCVTexture::init_type();
  OpenCVTexture::register_with_read_factory();

  PandaSystem *ps = PandaSystem::get_global_ptr();
  ps->add_system("OpenCV");
  TexturePool *ts = TexturePool::get_global_ptr();
  ts->register_texture_type(OpenCVTexture::make_texture, "avi");
#endif // HAVE_OPENCV
}

<commit_msg>not sure if OpenCV can read .mpg files, but no harm in listing it<commit_after>// Filename: config_grutil.cxx
// Created by:  drose (24May00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "config_grutil.h"
#include "frameRateMeter.h"
#include "openCVTexture.h"
#include "pandaSystem.h"
#include "texturePool.h"

#include "dconfig.h"

Configure(config_grutil);
NotifyCategoryDef(grutil, "");

ConfigureFn(config_grutil) {
  init_libgrutil();
}

ConfigVariableDouble frame_rate_meter_update_interval
("frame-rate-meter-update-interval", 1.5);

ConfigVariableString frame_rate_meter_text_pattern
("frame-rate-meter-text-pattern", "%0.1f fps");

ConfigVariableInt frame_rate_meter_layer_sort
("frame-rate-meter-layer-sort", 1000);

ConfigVariableDouble frame_rate_meter_scale
("frame-rate-meter-scale", 0.05);

ConfigVariableDouble frame_rate_meter_side_margins
("frame-rate-meter-side-margins", 0.5);

////////////////////////////////////////////////////////////////////
//     Function: init_libgrutil
//  Description: Initializes the library.  This must be called at
//               least once before any of the functions or classes in
//               this library can be used.  Normally it will be
//               called by the static initializers and need not be
//               called explicitly, but special cases exist.
////////////////////////////////////////////////////////////////////
void
init_libgrutil() {
  static bool initialized = false;
  if (initialized) {
    return;
  }
  initialized = true;

  FrameRateMeter::init_type();

#ifdef HAVE_OPENCV
  OpenCVTexture::init_type();
  OpenCVTexture::register_with_read_factory();

  PandaSystem *ps = PandaSystem::get_global_ptr();
  ps->add_system("OpenCV");
  TexturePool *ts = TexturePool::get_global_ptr();
  ts->register_texture_type(OpenCVTexture::make_texture, "avi mpg");
#endif // HAVE_OPENCV
}

<|endoftext|>


<commit_before>// Given an array of integers, every element appears three times except for one,
// which appears exactly once. Find that single one.
// Note:
// Your algorithm should have a linear runtime complexity. Could you implement
// it without using extra memory?

// digital design, simplify truth table
// Use a and b to represent 3 states
// ab has 3 value, 00, 01, 10
// ab      c       ab
// 00      0       00
// 01      0       01
// 10      0       10
// 00      1       01
// 01      1       10
// 10      1       00
// 1st solution
// a = ~abc + a~b~c;
// b = ~a~bc + ~ab~c;
// 2nd way
// b = b~c~a + ~bc~a = (b xor c) ~a;
// a = ~a~newbc + a~newb~c = (a xor c) ~newb;
class Solution {
  public:
    int singleNumber(vector<int> &nums) {
        int a = 0, tempa;
        int b = 0;
        for (int &c : nums) {
            b = ~a & (b ^ c);
            a = ~b & (a ^ c);
        }
        // a is the one appear twice
        // b is the one appear exactly once
        return b;
    }
};<commit_msg>optimize 137<commit_after>// Given an array of integers, every element appears three times except for one,
// which appears exactly once. Find that single one.
// Note:
// Your algorithm should have a linear runtime complexity. Could you implement
// it without using extra memory?

// digital design, simplify truth table
// Use a and b to represent 3 states
// ab has 3 value, 00, 01, 10
// ab      c       ab
// 00      0       00
// 01      0       01
// 10      0       10
// 00      1       01
// 01      1       10
// 10      1       00
// 1st solution
// a = ~abc + a~b~c;
// b = ~a~bc + ~ab~c;
// 2nd way
// b = b~c~a + ~bc~a = (b xor c) ~a;
// a = ~a~newbc + a~newb~c = (a xor c) ~newb;
class Solution {
  public:
    int singleNumber(vector<int> &nums) {
        int a = 0;
        int b = 0;
        for (int &c : nums) {
            b = ~a & (b ^ c);
            a = ~b & (a ^ c);
        }
        // a is the one appear twice
        // b is the one appear exactly once
        return b;
    }
};<|endoftext|>


<commit_before>/*****************************************************************************
 * Project: BaBar detector at the SLAC PEP-II B-factory
 * Package: RooFitCore
 *    File: $Id: RooAbsCategory.cc,v 1.29 2001/10/08 05:20:10 verkerke Exp $
 * Authors:
 *   DK, David Kirkby, Stanford University, kirkby@hep.stanford.edu
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu
 * History:
 *   07-Mar-2001 WV Created initial version
 *
 * Copyright (C) 2001 University of California
 *****************************************************************************/

// -- CLASS DESCRIPTION [CAT] --
// RooAbsCategory is the common abstract base class for objects that represent a
// discrete value with a finite number of states. Each state consist of a
// label/index pair, which is stored in a RooCatType object.
//
// Implementation of RooAbsCategory may be derived, there no interface
// is provided to modify the contents, nor a public interface to define states.

#include <iostream.h>
#include <stdlib.h>
#include "TString.h"
#include "TH1.h"
#include "TTree.h"
#include "TLeaf.h"
#include "RooFitCore/RooAbsCategory.hh"
#include "RooFitCore/RooArgSet.hh"
#include "RooFitCore/Roo1DTable.hh"
#include "RooFitCore/RooCategory.hh"
#include "RooFitCore/RooCatBinIter.hh"

ClassImp(RooAbsCategory)
;

RooAbsCategory::RooAbsCategory(const char *name, const char *title) :
  RooAbsArg(name,title)
{
  // Constructor
  setValueDirty() ;
  setShapeDirty() ;
}

RooAbsCategory::RooAbsCategory(const RooAbsCategory& other,const char* name) :
  RooAbsArg(other,name), _value(other._value)
{
  // Copy constructor, copies the registered category states from the original.
  TIterator* iter=other._types.MakeIterator() ;
  TObject* obj ;
  while (obj=iter->Next()) {
    _types.Add(obj->Clone()) ;
  }
  delete iter ;

  setValueDirty() ;
  setShapeDirty() ;
}

RooAbsCategory::~RooAbsCategory()
{
  // Destructor

  // We own the contents of _types
  _types.Delete() ;
}

Int_t RooAbsCategory::getIndex() const
{
  // Return index number of current state

  if (isValueDirty() || isShapeDirty()) {
    _value = traceEval() ;

    clearValueDirty() ;
    clearShapeDirty() ;
  }

  return _value.getVal() ;
}

const char* RooAbsCategory::getLabel() const
{
  // Return label string of current state

  if (isValueDirty() || isShapeDirty()) {
    _value = traceEval() ;

    clearValueDirty() ;
    clearShapeDirty() ;
  }

  return _value.GetName() ;
}

RooCatType RooAbsCategory::traceEval() const
{
  // Recalculate current value and check validity of new result.

  RooCatType value = evaluate() ;

  // Standard tracing code goes here
  if (!isValid(value)) {
  }

  // Call optional subclass tracing code
  traceEvalHook(value) ;

  return value ;
}

TIterator* RooAbsCategory::typeIterator() const
{
  // Return iterator over all defined states
  return _types.MakeIterator() ;
}

Bool_t RooAbsCategory::operator==(Int_t index) const
{
  // Equality operator with a integer (compares with state index number)
  return (index==getIndex()) ;
}

Bool_t RooAbsCategory::operator==(const char* label) const
{
  // Equality operator with a string (compares with state label string)
  return !TString(label).CompareTo(getLabel()) ;
}

Bool_t RooAbsCategory::isValidIndex(Int_t index) const
{
  // Check if state with given index is defined
  return lookupType(index)?kTRUE:kFALSE ;
}

Bool_t RooAbsCategory::isValidLabel(const char* label) const
{
  // Check if state with given name is defined
  return lookupType(label)?kTRUE:kFALSE ;
}

const RooCatType* RooAbsCategory::defineType(const char* label)
{
  // Define a new state with given name. The lowest available
  // integer number is assigned as index value

  // Find lowest unused index
  Int_t index(-1) ;
  while(lookupType(++index,kFALSE)) ;

  // Assign this index to given label
  return defineType(label,index) ;
}

const RooCatType* RooAbsCategory::defineType(const char* label, Int_t index)
{
  // Define new state with given name and index number.

  if (isValidIndex(index)) {
    cout << "RooAbsCategory::defineType(" << GetName() << "): index "
	 << index << " already assigned" << endl ;
    return 0 ;
  }

  if (isValidLabel(label)) {
    cout << "RooAbsCategory::defineType(" << GetName() << "): label "
	 << label << " already assigned or not allowed" << endl ;
    return 0 ;
  }

  Bool_t first = _types.GetEntries()?kFALSE:kTRUE ;
  RooCatType *newType = new RooCatType(label,index) ;
  _types.Add(newType) ;

  if (first) _value = RooCatType(label,index) ;
  setShapeDirty() ;

  return newType ;
}

void RooAbsCategory::clearTypes()
{
  // Delete all currently defined states

  _types.Delete() ;
  _value = RooCatType("",0) ;
  setShapeDirty() ;
}

const RooCatType* RooAbsCategory::lookupType(const RooCatType &other, Bool_t printError) const
{
  // Find our type that matches the specified type, or return 0 for no match.

  RooCatType* type ;
  Int_t n= _types.GetEntries();
  for (int i=0 ; i < n; i++) {
    type = (RooCatType*)_types.At(i) ;
    if((*type) == other) return type; // delegate comparison to RooCatType
  }

  if (printError) {
    cout << ClassName() << "::" << GetName() << ":lookupType: no match for ";
    other.printToStream(cout,OneLine);
  }
  return 0 ;
}

const RooCatType* RooAbsCategory::lookupType(Int_t index, Bool_t printError) const
{
  // Find our type corresponding to the specified index, or return 0 for no match.

  RooCatType* type ;
  Int_t n= _types.GetEntries();
  for (int i=0 ; i < n; i++) {
    type = (RooCatType*)_types.At(i) ;
    if((*type) == index) return type; // delegate comparison to RooCatType
  }
  if (printError) {
    cout << ClassName() << "::" << GetName() << ":lookupType: no match for index "
	 << index << endl;
  }
  return 0 ;
}

const RooCatType* RooAbsCategory::lookupType(const char* label, Bool_t printError) const
{
  // Find our type corresponding to the specified label, or return 0 for no match.

  RooCatType* type ;
  Int_t n= _types.GetEntries();
  for (int i=0 ; i < n; i++) {
    type = (RooCatType*)_types.At(i) ;
    if((*type) == label) return type; // delegate comparison to RooCatType
  }

  // Try if label represents integer number
  char* endptr ;
  Int_t idx=strtol(label,&endptr,10)  ;
  if (endptr==label+strlen(label)) {
    for (int i=0 ; i < n; i++) {
    type = (RooCatType*)_types.At(i) ;
    if((*type) == idx) return type; // delegate comparison to RooCatType
    }
  }

  if (printError) {
    cout << ClassName() << "::" << GetName() << ":lookupType: no match for label "
	 << label << endl;
  }
  return 0 ;
}

Bool_t RooAbsCategory::isValid() const
{
  // Check if current value is a valid state
  return isValid(_value) ;
}

Bool_t RooAbsCategory::isValid(RooCatType value)  const
{
  // Check if given state is defined for this object
  return isValidIndex(value.getVal()) ;
}

Roo1DTable* RooAbsCategory::createTable(const char *label)  const
{
  // Create a table matching the shape of this category
  return new Roo1DTable(GetName(),label,*this) ;
}

Bool_t RooAbsCategory::readFromStream(istream& is, Bool_t compact, Bool_t verbose)
{
  // Read object contents from stream (dummy for now)

  return kFALSE ;
}

void RooAbsCategory::writeToStream(ostream& os, Bool_t compact) const
{
  // Write object contents to stream
  if (compact) {
    os << getLabel() ;
  } else {
    os << getLabel() ;
  }
}

void RooAbsCategory::printToStream(ostream& os, PrintOption opt, TString indent) const
{
  // Print info about this object to the specified stream. In addition to the info
  // from RooAbsArg::printToStream() we add:
  //
  //     Shape : label, index, defined types

  RooAbsArg::printToStream(os,opt,indent);
  if(opt >= Shape) {
    os << indent << "--- RooAbsCategory ---" << endl;
    if (_types.GetEntries()==0) {
      os << indent << "  ** No values defined **" << endl;
      return;
    }
    os << indent << "  Value is \"" << getLabel() << "\" (" << getIndex() << ")" << endl;
    os << indent << "  Has the following possible values:" << endl;
    indent.Append("    ");
    opt= lessVerbose(opt);
    RooCatType *type;
    Int_t n= _types.GetEntries();
    for (int i=0 ; i < n ; i++) {
      type= (RooCatType*)_types.At(i);
      os << indent;
      type->printToStream(os,opt,indent);
    }
  }
}

void RooAbsCategory::attachToTree(TTree& t, Int_t bufSize)
{
  // Attach the category index and label to as branches
  // to the given TTree. The index field will be attached
  // as integer with name <name>_idx, the label field will be attached
  // as char[] with label <name>_lbl.

  // First check if there is an integer branch matching the category name
  TBranch* branch = t.GetBranch(GetName()) ;
  if (branch) {

    TString typeName(((TLeaf*)branch->GetListOfLeaves()->At(0))->GetTypeName()) ;
    if (!typeName.CompareTo("Int_t")) {
      // Imported TTree: attach only index field as branch

      cout << "RooAbsCategory::attachToTree(" << GetName() << ") TTree branch " << GetName()
	   << " interpreted as category index" << endl ;

      t.SetBranchAddress(GetName(),&((Int_t&)_value._value)) ;
      setAttribute("INTIDXONLY_TREE_BRANCH",kTRUE) ;
      return ;
    }
  }

  // Native TTree: attach both index and label of category as branches

  TString idxName(GetName()) ;
  TString lblName(GetName()) ;
  idxName.Append("_idx") ;
  lblName.Append("_lbl") ;

  // First determine if branch is taken
  if (t.GetBranch(idxName)) {
    t.SetBranchAddress(idxName,&((Int_t&)_value._value)) ;
    } else {
      TString format(idxName);
      format.Append("/I");
      void* ptr = &(_value._value) ;
      t.Branch(idxName, ptr, (const Text_t*)format, bufSize);
    }

  // First determine if branch is taken
  if (t.GetBranch(lblName)) {
    t.SetBranchAddress(lblName,_value._label) ;
  } else {
    TString format(lblName);
    format.Append("/C");
    void* ptr = _value._label ;
    t.Branch(lblName, ptr, (const Text_t*)format, bufSize);
  }
}

void RooAbsCategory::fillTreeBranch(TTree& t)
{
  // Attach object to a branch of given TTree

  TString idxName(GetName()) ;
  TString lblName(GetName()) ;
  idxName.Append("_idx") ;
  lblName.Append("_lbl") ;

  // First determine if branch is taken
  TBranch* idxBranch = t.GetBranch(idxName) ;
  TBranch* lblBranch = t.GetBranch(lblName) ;
  if (!idxBranch||!lblBranch) {
    cout << "RooAbsCategory::fillTreeBranch(" << GetName() << ") ERROR: not attached to tree" << endl ;
    assert(0) ;
  }

  idxBranch->Fill() ;
  lblBranch->Fill() ;
}

void RooAbsCategory::copyCache(const RooAbsArg* source)
{
  // Copy the cached value from given source and raise dirty flag.
  // It is the callers responsability to unsure that the sources
  // cache is clean before this function is called, e.g. by
  // calling syncCache() on the source.

  RooAbsCategory* other = dynamic_cast<RooAbsCategory*>(const_cast<RooAbsArg*>(source)) ;
  assert(other!=0) ;

  if (source->getAttribute("INTIDXONLY_TREE_BRANCH")) {
    // Lookup cat state from other-index because label is missing
    cout << "other->_value._value = " << other->_value._value << endl ;
    const RooCatType* type = lookupType(other->_value._value) ;
    if (type) {
      _value = *type ;
    } else {
      cout << "RooAbsCategory::copyCache(" << GetName()
	   << ") ERROR: index of source arg " << source->GetName()
	   << " is invalid, value not updated" << endl ;
    }
  } else {
    _value = other->_value ;
  }

  setValueDirty() ;
}

const RooCatType* RooAbsCategory::getOrdinal(UInt_t n) const
{
  // Return state definition of ordinal nth defined state,
  // needed by the generator mechanism.

  return (const RooCatType*)_types.At(n);
}

RooAbsArg *RooAbsCategory::createFundamental(const char* newname) const
{
  // Create a RooCategory fundamental object with our properties.

  // Add and precalculate new category column
  RooCategory *fund= new RooCategory(newname?newname:GetName(),GetTitle()) ;

  // Copy states
  TIterator* tIter = typeIterator() ;
  RooCatType* type ;
  while (type=(RooCatType*)tIter->Next()) {
    ((RooAbsCategory*)fund)->defineType(type->GetName(),type->getVal()) ;
  }
  delete tIter;

  return fund;
}

Bool_t RooAbsCategory::isSignType(Bool_t mustHaveZero) const
{
  // Determine if category has 2 or 3 states with index values -1,0,1

  if (numTypes()>3||numTypes()<2) return kFALSE ;
  if (mustHaveZero&&numTypes()!=3) return kFALSE ;

  Bool_t ret(kTRUE) ;
  TIterator* tIter = typeIterator() ;
  RooCatType* type ;
  while(type=(RooCatType*)tIter->Next()) {
    if (abs(type->getVal())>1) ret=kFALSE ;
  }

  delete tIter ;
  return ret ;
}
<commit_msg><commit_after>/*****************************************************************************
 * Project: BaBar detector at the SLAC PEP-II B-factory
 * Package: RooFitCore
 *    File: $Id: RooAbsCategory.cc,v 1.30 2001/10/19 06:56:51 verkerke Exp $
 * Authors:
 *   DK, David Kirkby, Stanford University, kirkby@hep.stanford.edu
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu
 * History:
 *   07-Mar-2001 WV Created initial version
 *
 * Copyright (C) 2001 University of California
 *****************************************************************************/

// -- CLASS DESCRIPTION [CAT] --
// RooAbsCategory is the common abstract base class for objects that represent a
// discrete value with a finite number of states. Each state consist of a
// label/index pair, which is stored in a RooCatType object.
//
// Implementation of RooAbsCategory may be derived, there no interface
// is provided to modify the contents, nor a public interface to define states.

#include <iostream.h>
#include <stdlib.h>
#include "TString.h"
#include "TH1.h"
#include "TTree.h"
#include "TLeaf.h"
#include "RooFitCore/RooAbsCategory.hh"
#include "RooFitCore/RooArgSet.hh"
#include "RooFitCore/Roo1DTable.hh"
#include "RooFitCore/RooCategory.hh"
#include "RooFitCore/RooCatBinIter.hh"

ClassImp(RooAbsCategory)
;

RooAbsCategory::RooAbsCategory(const char *name, const char *title) :
  RooAbsArg(name,title)
{
  // Constructor
  setValueDirty() ;
  setShapeDirty() ;
}

RooAbsCategory::RooAbsCategory(const RooAbsCategory& other,const char* name) :
  RooAbsArg(other,name), _value(other._value)
{
  // Copy constructor, copies the registered category states from the original.
  TIterator* iter=other._types.MakeIterator() ;
  TObject* obj ;
  while (obj=iter->Next()) {
    _types.Add(obj->Clone()) ;
  }
  delete iter ;

  setValueDirty() ;
  setShapeDirty() ;
}

RooAbsCategory::~RooAbsCategory()
{
  // Destructor

  // We own the contents of _types
  _types.Delete() ;
}

Int_t RooAbsCategory::getIndex() const
{
  // Return index number of current state

  if (isValueDirty() || isShapeDirty()) {
    _value = traceEval() ;

    clearValueDirty() ;
    clearShapeDirty() ;
  }

  return _value.getVal() ;
}

const char* RooAbsCategory::getLabel() const
{
  // Return label string of current state

  if (isValueDirty() || isShapeDirty()) {
    _value = traceEval() ;

    clearValueDirty() ;
    clearShapeDirty() ;
  }

  return _value.GetName() ;
}

RooCatType RooAbsCategory::traceEval() const
{
  // Recalculate current value and check validity of new result.

  RooCatType value = evaluate() ;

  // Standard tracing code goes here
  if (!isValid(value)) {
  }

  // Call optional subclass tracing code
  traceEvalHook(value) ;

  return value ;
}

TIterator* RooAbsCategory::typeIterator() const
{
  // Return iterator over all defined states
  return _types.MakeIterator() ;
}

Bool_t RooAbsCategory::operator==(Int_t index) const
{
  // Equality operator with a integer (compares with state index number)
  return (index==getIndex()) ;
}

Bool_t RooAbsCategory::operator==(const char* label) const
{
  // Equality operator with a string (compares with state label string)
  return !TString(label).CompareTo(getLabel()) ;
}

Bool_t RooAbsCategory::isValidIndex(Int_t index) const
{
  // Check if state with given index is defined
  return lookupType(index)?kTRUE:kFALSE ;
}

Bool_t RooAbsCategory::isValidLabel(const char* label) const
{
  // Check if state with given name is defined
  return lookupType(label)?kTRUE:kFALSE ;
}

const RooCatType* RooAbsCategory::defineType(const char* label)
{
  // Define a new state with given name. The lowest available
  // integer number is assigned as index value

  // Find lowest unused index
  Int_t index(-1) ;
  while(lookupType(++index,kFALSE)) ;

  // Assign this index to given label
  return defineType(label,index) ;
}

const RooCatType* RooAbsCategory::defineType(const char* label, Int_t index)
{
  // Define new state with given name and index number.

  if (isValidIndex(index)) {
    cout << "RooAbsCategory::defineType(" << GetName() << "): index "
	 << index << " already assigned" << endl ;
    return 0 ;
  }

  if (isValidLabel(label)) {
    cout << "RooAbsCategory::defineType(" << GetName() << "): label "
	 << label << " already assigned or not allowed" << endl ;
    return 0 ;
  }

  Bool_t first = _types.GetEntries()?kFALSE:kTRUE ;
  RooCatType *newType = new RooCatType(label,index) ;
  _types.Add(newType) ;

  if (first) _value = RooCatType(label,index) ;
  setShapeDirty() ;

  return newType ;
}

void RooAbsCategory::clearTypes()
{
  // Delete all currently defined states

  _types.Delete() ;
  _value = RooCatType("",0) ;
  setShapeDirty() ;
}

const RooCatType* RooAbsCategory::lookupType(const RooCatType &other, Bool_t printError) const
{
  // Find our type that matches the specified type, or return 0 for no match.

  RooCatType* type ;
  Int_t n= _types.GetEntries();
  for (int i=0 ; i < n; i++) {
    type = (RooCatType*)_types.At(i) ;
    if((*type) == other) return type; // delegate comparison to RooCatType
  }

  if (printError) {
    cout << ClassName() << "::" << GetName() << ":lookupType: no match for ";
    other.printToStream(cout,OneLine);
  }
  return 0 ;
}

const RooCatType* RooAbsCategory::lookupType(Int_t index, Bool_t printError) const
{
  // Find our type corresponding to the specified index, or return 0 for no match.

  RooCatType* type ;
  Int_t n= _types.GetEntries();
  for (int i=0 ; i < n; i++) {
    type = (RooCatType*)_types.At(i) ;
    if((*type) == index) return type; // delegate comparison to RooCatType
  }
  if (printError) {
    cout << ClassName() << "::" << GetName() << ":lookupType: no match for index "
	 << index << endl;
  }
  return 0 ;
}

const RooCatType* RooAbsCategory::lookupType(const char* label, Bool_t printError) const
{
  // Find our type corresponding to the specified label, or return 0 for no match.

  RooCatType* type ;
  Int_t n= _types.GetEntries();
  for (int i=0 ; i < n; i++) {
    type = (RooCatType*)_types.At(i) ;
    if((*type) == label) return type; // delegate comparison to RooCatType
  }

  // Try if label represents integer number
  char* endptr ;
  Int_t idx=strtol(label,&endptr,10)  ;
  if (endptr==label+strlen(label)) {
    for (int i=0 ; i < n; i++) {
    type = (RooCatType*)_types.At(i) ;
    if((*type) == idx) return type; // delegate comparison to RooCatType
    }
  }

  if (printError) {
    cout << ClassName() << "::" << GetName() << ":lookupType: no match for label "
	 << label << endl;
  }
  return 0 ;
}

Bool_t RooAbsCategory::isValid() const
{
  // Check if current value is a valid state
  return isValid(_value) ;
}

Bool_t RooAbsCategory::isValid(RooCatType value)  const
{
  // Check if given state is defined for this object
  return isValidIndex(value.getVal()) ;
}

Roo1DTable* RooAbsCategory::createTable(const char *label)  const
{
  // Create a table matching the shape of this category
  return new Roo1DTable(GetName(),label,*this) ;
}

Bool_t RooAbsCategory::readFromStream(istream& is, Bool_t compact, Bool_t verbose)
{
  // Read object contents from stream (dummy for now)

  return kFALSE ;
}

void RooAbsCategory::writeToStream(ostream& os, Bool_t compact) const
{
  // Write object contents to stream
  if (compact) {
    os << getLabel() ;
  } else {
    os << getLabel() ;
  }
}

void RooAbsCategory::printToStream(ostream& os, PrintOption opt, TString indent) const
{
  // Print info about this object to the specified stream. In addition to the info
  // from RooAbsArg::printToStream() we add:
  //
  //     Shape : label, index, defined types

  RooAbsArg::printToStream(os,opt,indent);
  if(opt >= Shape) {
    os << indent << "--- RooAbsCategory ---" << endl;
    if (_types.GetEntries()==0) {
      os << indent << "  ** No values defined **" << endl;
      return;
    }
    os << indent << "  Value is \"" << getLabel() << "\" (" << getIndex() << ")" << endl;
    os << indent << "  Has the following possible values:" << endl;
    indent.Append("    ");
    opt= lessVerbose(opt);
    RooCatType *type;
    Int_t n= _types.GetEntries();
    for (int i=0 ; i < n ; i++) {
      type= (RooCatType*)_types.At(i);
      os << indent;
      type->printToStream(os,opt,indent);
    }
  }
}

void RooAbsCategory::attachToTree(TTree& t, Int_t bufSize)
{
  // Attach the category index and label to as branches
  // to the given TTree. The index field will be attached
  // as integer with name <name>_idx, the label field will be attached
  // as char[] with label <name>_lbl.

  // First check if there is an integer branch matching the category name
  TBranch* branch = t.GetBranch(GetName()) ;
  if (branch) {

    TString typeName(((TLeaf*)branch->GetListOfLeaves()->At(0))->GetTypeName()) ;
    if (!typeName.CompareTo("Int_t")) {
      // Imported TTree: attach only index field as branch

      cout << "RooAbsCategory::attachToTree(" << GetName() << ") TTree branch " << GetName()
	   << " will be interpreted as category index" << endl ;

      t.SetBranchAddress(GetName(),&((Int_t&)_value._value)) ;
      setAttribute("INTIDXONLY_TREE_BRANCH",kTRUE) ;
      return ;
    } else if (!typeName.CompareTo("UChar_t")) {
      cout << "RooAbsReal::attachToTree(" << GetName() << ") TTree Bool_t branch " << GetName()
	   << " will be interpreted as category with index values 0 and 1 " << endl ;
      t.SetBranchAddress(GetName(),&((Bool_t&)_value._value)) ;
      setAttribute("BOOL_TREE_BRANCH",kTRUE) ;
      return ;
    }
  }

  // Native TTree: attach both index and label of category as branches
  TString idxName(GetName()) ;
  TString lblName(GetName()) ;
  idxName.Append("_idx") ;
  lblName.Append("_lbl") ;

  // First determine if branch is taken
  if (t.GetBranch(idxName)) {
    t.SetBranchAddress(idxName,&((Int_t&)_value._value)) ;
  } else {
    TString format(idxName);
    format.Append("/I");
    void* ptr = &(_value._value) ;
    t.Branch(idxName, ptr, (const Text_t*)format, bufSize);
  }

  // First determine if branch is taken
  if (t.GetBranch(lblName)) {
    t.SetBranchAddress(lblName,_value._label) ;
  } else {
    TString format(lblName);
    format.Append("/C");
    void* ptr = _value._label ;
    t.Branch(lblName, ptr, (const Text_t*)format, bufSize);
  }
}

void RooAbsCategory::fillTreeBranch(TTree& t)
{
  // Attach object to a branch of given TTree

  TString idxName(GetName()) ;
  TString lblName(GetName()) ;
  idxName.Append("_idx") ;
  lblName.Append("_lbl") ;

  // First determine if branch is taken
  TBranch* idxBranch = t.GetBranch(idxName) ;
  TBranch* lblBranch = t.GetBranch(lblName) ;
  if (!idxBranch||!lblBranch) {
    cout << "RooAbsCategory::fillTreeBranch(" << GetName() << ") ERROR: not attached to tree" << endl ;
    assert(0) ;
  }

  idxBranch->Fill() ;
  lblBranch->Fill() ;
}

void RooAbsCategory::copyCache(const RooAbsArg* source)
{
  // Copy the cached value from given source and raise dirty flag.
  // It is the callers responsability to unsure that the sources
  // cache is clean before this function is called, e.g. by
  // calling syncCache() on the source.

  RooAbsCategory* other = dynamic_cast<RooAbsCategory*>(const_cast<RooAbsArg*>(source)) ;
  assert(other!=0) ;

  if (source->getAttribute("INTIDXONLY_TREE_BRANCH")) {
    // Lookup cat state from other-index because label is missing
    const RooCatType* type = lookupType(other->_value._value) ;
    if (type) {
      _value = *type ;
    } else {
      cout << "RooAbsCategory::copyCache(" << GetName()
	   << ") ERROR: index of source arg " << source->GetName()
	   << " is invalid (" << other->_value._value
	   << "), value not updated" << endl ;
    }
  } if (source->getAttribute("BOOL_TREE_BRANCH")) {
    // Lookup cat state from other-index because label is missing
    Bool_t& tmp = (Bool_t&) other->_value._value ;
    const RooCatType* type = lookupType(tmp?1:0) ;
    if (type) {
      _value = *type ;
    } else {
      cout << "RooAbsCategory::copyCache(" << GetName()
	   << ") ERROR: index of source arg " << source->GetName()
	   << " is invalid (" << (tmp?1:0) << "), value not updated" << endl ;
    }
  } else {
    _value = other->_value ;
  }

  setValueDirty() ;
}

const RooCatType* RooAbsCategory::getOrdinal(UInt_t n) const
{
  // Return state definition of ordinal nth defined state,
  // needed by the generator mechanism.

  return (const RooCatType*)_types.At(n);
}

RooAbsArg *RooAbsCategory::createFundamental(const char* newname) const
{
  // Create a RooCategory fundamental object with our properties.

  // Add and precalculate new category column
  RooCategory *fund= new RooCategory(newname?newname:GetName(),GetTitle()) ;

  // Copy states
  TIterator* tIter = typeIterator() ;
  RooCatType* type ;
  while (type=(RooCatType*)tIter->Next()) {
    ((RooAbsCategory*)fund)->defineType(type->GetName(),type->getVal()) ;
  }
  delete tIter;

  return fund;
}

Bool_t RooAbsCategory::isSignType(Bool_t mustHaveZero) const
{
  // Determine if category has 2 or 3 states with index values -1,0,1

  if (numTypes()>3||numTypes()<2) return kFALSE ;
  if (mustHaveZero&&numTypes()!=3) return kFALSE ;

  Bool_t ret(kTRUE) ;
  TIterator* tIter = typeIterator() ;
  RooCatType* type ;
  while(type=(RooCatType*)tIter->Next()) {
    if (abs(type->getVal())>1) ret=kFALSE ;
  }

  delete tIter ;
  return ret ;
}
<|endoftext|>