<commit_before>
#include <algorithms/class_algorithm_status.h>
#include <config/enums.h>
#include <h5pp/h5pp.h>
#include <string>
#include <tools/common/io.h>
#include <tools/common/log.h>
#include <tools/common/prof.h>

namespace tools::common::io::h5attr {
    template<typename AttrType>
    void save_attr(h5pp::File &file, const AttrType &attrData, const std::string &attrName, const std::string &dsetPath, const std::string &dsetText) {
        tools::log->trace("Attribute -- {: <40} = {: <40} on dset: {}", attrName, attrData, dsetPath);
        if(not file.linkExists(dsetPath)) file.writeDataset(dsetText, dsetPath);
        file.writeAttribute(attrData, attrName, dsetPath);
    }
}

namespace tools::common::io::h5attr {
    void bootstrap_save_log(std::unordered_map<std::string, std::pair<uint64_t, uint64_t>> &save_log, const h5pp::File &h5ppFile,
                            const std::string &state_prefix) {
        if(save_log.empty()) {
            try {
                uint64_t step = 0;
                uint64_t iter = 0;
                if(h5ppFile.linkExists("common/step")) step = h5ppFile.readAttribute<uint64_t>(state_prefix, "common/step");
                if(h5ppFile.linkExists("common/iteration")) iter = h5ppFile.readAttribute<uint64_t>(state_prefix, "common/iteration");
                save_log[state_prefix] = std::make_pair(iter, step);

            } catch(const std::exception &ex) { tools::log->warn("Could not bootstrap save_log: {}", ex.what()); }
        }
    }
}

void tools::common::io::h5attr::save_meta(h5pp::File &h5ppFile, const StorageLevel &storage_level, const StorageReason &storage_reason,
                                          const ModelType &model_type, size_t model_size, const AlgorithmType &algo_type, const std::string &state_name,
                                          const std::string &state_prefix, const std::string &model_prefix, const class_algorithm_status &status) {
    // Write metadata into /common so that we can find state paths later.
    // Under /common we have the following dummy datasets defining attributes which map state_prefix to useful information:
    //
    // -- finished       | true or 1 if state_prefix is finished
    // -- storage_level  | state_prefix -> storage_level
    // -- storage_reason | state_prefix -> storage_reason
    // -- state_root     | state_prefix -> state_root
    // -- hamiltonian    | state_prefix -> path to hamiltonian table
    // -- mps_prefix     | state_prefix -> mps_prefix
    // -- mpo_prefix     | state_prefix -> mpo_prefix
    // -- model_type     | state_prefix -> model_type
    // -- model_size     | state_prefix -> model_size
    // -- algo_type      | state_prefix -> algo_type
    // -- state_name     | state_prefix -> state_name
    // -- iteration      | state_prefix -> iteration
    // -- step           | state_prefix -> step
    // -- position       | state_prefix -> position of the mps

    // Checks if the current entries have already been written
    static std::unordered_map<std::string, std::pair<uint64_t, uint64_t>> save_log;
    bootstrap_save_log(save_log, h5ppFile, state_prefix);

    auto save_point = std::make_pair(status.iter, status.step);
    if(save_log[state_prefix] == save_point) return;

    tools::common::profile::get_default_prof()["t_hdf"]->tic();

    std::string storage_level_str(enum2str(storage_level));
    std::string storage_reason_str(enum2str(storage_reason));
    std::string model_name(enum2str(model_type));
    std::string algo_name(enum2str(algo_type));
    std::string state_root  = algo_name + '/' + state_name;
    std::string hamiltonian = model_prefix + "/hamiltonian";
    std::string mpo_prefix  = model_prefix + "/mpo";
    std::string mps_prefix  = state_prefix + "/mps";

    save_attr(h5ppFile, status.algorithm_has_finished, state_prefix, "common/finished", "Maps state_prefix -> finished");
    save_attr(h5ppFile, storage_level_str, state_prefix, "common/storage_level", "Maps state_prefix -> storage_level");
    save_attr(h5ppFile, storage_reason_str, state_prefix, "common/storage_reason", "Maps state_prefix -> storage_reason");
    save_attr(h5ppFile, state_root, state_prefix, "common/state_root", "Maps state_prefix -> state_root");
    save_attr(h5ppFile, model_prefix, state_prefix, "common/model_prefix", "Maps state_prefix -> model_prefix");
    save_attr(h5ppFile, hamiltonian, state_prefix, "common/hamiltonian", "Maps state_prefix -> hamiltonian");
    save_attr(h5ppFile, mpo_prefix, state_prefix, "common/mpo_prefix", "Maps state_prefix -> mpo_prefix");
    save_attr(h5ppFile, mps_prefix, state_prefix, "common/mps_prefix", "Maps state_prefix -> mps_prefix");
    save_attr(h5ppFile, model_name, state_prefix, "common/model_type", "Maps state_prefix -> model_type");
    save_attr(h5ppFile, model_size, state_prefix, "common/model_size", "Maps state_prefix -> model_size");
    save_attr(h5ppFile, algo_name, state_prefix, "common/algo_type", "Maps state_prefix -> algo_type");
    save_attr(h5ppFile, state_name, state_prefix, "common/state_name", "Maps state_prefix -> state_name");
    save_attr(h5ppFile, status.iter, state_prefix, "common/iteration", "Maps state_prefix -> iteration");
    save_attr(h5ppFile, status.step, state_prefix, "common/step", "Maps state_prefix -> step");
    save_attr(h5ppFile, status.position, state_prefix, "common/position", "Maps state_prefix -> position");
    save_log[state_prefix] = save_point;
    tools::common::profile::get_default_prof()["t_hdf"]->toc();
}
<commit_msg>Improved logging<commit_after>
#include <algorithms/class_algorithm_status.h>
#include <config/enums.h>
#include <h5pp/h5pp.h>
#include <string>
#include <tools/common/io.h>
#include <tools/common/log.h>
#include <tools/common/prof.h>

namespace tools::common::io::h5attr {
    template<typename AttrType>
    void save_attr(h5pp::File &file, const AttrType &attrData, const std::string &attrName, const std::string &dsetPath, const std::string &dsetText) {
        tools::log->trace("Attribute -- {: <40} = {: <40} on dset: {}", attrName, attrData, dsetPath);
        if(not file.linkExists(dsetPath)) file.writeDataset(dsetText, dsetPath);
        file.writeAttribute(attrData, attrName, dsetPath);
    }
}

namespace tools::common::io::h5attr {
    void bootstrap_save_log(std::unordered_map<std::string, std::pair<uint64_t, uint64_t>> &save_log, const h5pp::File &h5ppFile,
                            const std::string &state_prefix) {
        if(save_log.empty()) {
            try {
                uint64_t step = 0;
                uint64_t iter = 0;
                if(h5ppFile.linkExists("common/step")) step = h5ppFile.readAttribute<uint64_t>(state_prefix, "common/step");
                if(h5ppFile.linkExists("common/iteration")) iter = h5ppFile.readAttribute<uint64_t>(state_prefix, "common/iteration");
                save_log[state_prefix] = std::make_pair(iter, step);

            } catch(const std::exception &ex) { tools::log->warn("Could not bootstrap save_log for {}: {}", state_prefix, ex.what()); }
        }
    }
}

void tools::common::io::h5attr::save_meta(h5pp::File &h5ppFile, const StorageLevel &storage_level, const StorageReason &storage_reason,
                                          const ModelType &model_type, size_t model_size, const AlgorithmType &algo_type, const std::string &state_name,
                                          const std::string &state_prefix, const std::string &model_prefix, const class_algorithm_status &status) {
    // Write metadata into /common so that we can find state paths later.
    // Under /common we have the following dummy datasets defining attributes which map state_prefix to useful information:
    //
    // -- finished       | true or 1 if state_prefix is finished
    // -- storage_level  | state_prefix -> storage_level
    // -- storage_reason | state_prefix -> storage_reason
    // -- state_root     | state_prefix -> state_root
    // -- hamiltonian    | state_prefix -> path to hamiltonian table
    // -- mps_prefix     | state_prefix -> mps_prefix
    // -- mpo_prefix     | state_prefix -> mpo_prefix
    // -- model_type     | state_prefix -> model_type
    // -- model_size     | state_prefix -> model_size
    // -- algo_type      | state_prefix -> algo_type
    // -- state_name     | state_prefix -> state_name
    // -- iteration      | state_prefix -> iteration
    // -- step           | state_prefix -> step
    // -- position       | state_prefix -> position of the mps

    // Checks if the current entries have already been written
    static std::unordered_map<std::string, std::pair<uint64_t, uint64_t>> save_log;
    bootstrap_save_log(save_log, h5ppFile, state_prefix);

    auto save_point = std::make_pair(status.iter, status.step);
    if(save_log[state_prefix] == save_point) return;

    tools::common::profile::get_default_prof()["t_hdf"]->tic();

    std::string storage_level_str(enum2str(storage_level));
    std::string storage_reason_str(enum2str(storage_reason));
    std::string model_name(enum2str(model_type));
    std::string algo_name(enum2str(algo_type));
    std::string state_root  = algo_name + '/' + state_name;
    std::string hamiltonian = model_prefix + "/hamiltonian";
    std::string mpo_prefix  = model_prefix + "/mpo";
    std::string mps_prefix  = state_prefix + "/mps";

    save_attr(h5ppFile, status.algorithm_has_finished, state_prefix, "common/finished", "Maps state_prefix -> finished");
    save_attr(h5ppFile, storage_level_str, state_prefix, "common/storage_level", "Maps state_prefix -> storage_level");
    save_attr(h5ppFile, storage_reason_str, state_prefix, "common/storage_reason", "Maps state_prefix -> storage_reason");
    save_attr(h5ppFile, state_root, state_prefix, "common/state_root", "Maps state_prefix -> state_root");
    save_attr(h5ppFile, model_prefix, state_prefix, "common/model_prefix", "Maps state_prefix -> model_prefix");
    save_attr(h5ppFile, hamiltonian, state_prefix, "common/hamiltonian", "Maps state_prefix -> hamiltonian");
    save_attr(h5ppFile, mpo_prefix, state_prefix, "common/mpo_prefix", "Maps state_prefix -> mpo_prefix");
    save_attr(h5ppFile, mps_prefix, state_prefix, "common/mps_prefix", "Maps state_prefix -> mps_prefix");
    save_attr(h5ppFile, model_name, state_prefix, "common/model_type", "Maps state_prefix -> model_type");
    save_attr(h5ppFile, model_size, state_prefix, "common/model_size", "Maps state_prefix -> model_size");
    save_attr(h5ppFile, algo_name, state_prefix, "common/algo_type", "Maps state_prefix -> algo_type");
    save_attr(h5ppFile, state_name, state_prefix, "common/state_name", "Maps state_prefix -> state_name");
    save_attr(h5ppFile, status.iter, state_prefix, "common/iteration", "Maps state_prefix -> iteration");
    save_attr(h5ppFile, status.step, state_prefix, "common/step", "Maps state_prefix -> step");
    save_attr(h5ppFile, status.position, state_prefix, "common/position", "Maps state_prefix -> position");
    save_log[state_prefix] = save_point;
    tools::common::profile::get_default_prof()["t_hdf"]->toc();
}
<|endoftext|>


<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

namespace MATH_NAMESPACE
{
namespace detail
{

//-------------------------------------------------------------------------------------------------
// Convert float to unorm (cf. OpenGL 4.4, 2.3.4.1
//

template <unsigned Bits>
MATH_FUNC
inline uint32_t float_to_unorm(float f)
{
    f = saturate(f);
    return static_cast<uint32_t>(f * static_cast<double>((1ULL << Bits) - 1));
}

template <unsigned Bits>
MATH_FUNC
inline float unorm_to_float(uint32_t u)
{
    return static_cast<float>(u) / static_cast<double>((1ULL << Bits) - 1);
}

} // detail

//-------------------------------------------------------------------------------------------------
// unorm members
//

template <unsigned Bits>
MATH_FUNC
unorm<Bits>::unorm(float f)
    : value(detail::float_to_unorm<Bits>(f))
{
}

template <unsigned Bits>
MATH_FUNC
unorm<Bits>::operator value_type() const
{
    return value;
}

template <unsigned Bits>
MATH_FUNC
unorm<Bits>::operator float() const
{
    return detail::unorm_to_float<Bits>(value);
}

//-------------------------------------------------------------------------------------------------
// Comparisons
//

template <unsigned Bits>
MATH_FUNC
inline bool operator==(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) == static_cast<T>(b);
}

template <unsigned Bits>
MATH_FUNC
inline bool operator!=(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) != static_cast<T>(b);
}

template <unsigned Bits>
MATH_FUNC
inline bool operator<(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) < static_cast<T>(b);
}

template <unsigned Bits>
MATH_FUNC
inline bool operator<=(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) <= static_cast<T>(b);
}

template <unsigned Bits>
MATH_FUNC
inline bool operator>(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) > static_cast<T>(b);
}

template <unsigned Bits>
MATH_FUNC
inline bool operator>=(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) >= static_cast<T>(b);
}

} // MATH_NAMESPACE
<commit_msg>Fix a typo<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

namespace MATH_NAMESPACE
{
namespace detail
{

//-------------------------------------------------------------------------------------------------
// Convert float to unorm (cf. OpenGL 4.4, 2.3.4.1)
//

template <unsigned Bits>
MATH_FUNC
inline uint32_t float_to_unorm(float f)
{
    f = saturate(f);
    return static_cast<uint32_t>(f * static_cast<double>((1ULL << Bits) - 1));
}

template <unsigned Bits>
MATH_FUNC
inline float unorm_to_float(uint32_t u)
{
    return static_cast<float>(u) / static_cast<double>((1ULL << Bits) - 1);
}

} // detail

//-------------------------------------------------------------------------------------------------
// unorm members
//

template <unsigned Bits>
MATH_FUNC
unorm<Bits>::unorm(float f)
    : value(detail::float_to_unorm<Bits>(f))
{
}

template <unsigned Bits>
MATH_FUNC
unorm<Bits>::operator value_type() const
{
    return value;
}

template <unsigned Bits>
MATH_FUNC
unorm<Bits>::operator float() const
{
    return detail::unorm_to_float<Bits>(value);
}

//-------------------------------------------------------------------------------------------------
// Comparisons
//

template <unsigned Bits>
MATH_FUNC
inline bool operator==(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) == static_cast<T>(b);
}

template <unsigned Bits>
MATH_FUNC
inline bool operator!=(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) != static_cast<T>(b);
}

template <unsigned Bits>
MATH_FUNC
inline bool operator<(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) < static_cast<T>(b);
}

template <unsigned Bits>
MATH_FUNC
inline bool operator<=(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) <= static_cast<T>(b);
}

template <unsigned Bits>
MATH_FUNC
inline bool operator>(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) > static_cast<T>(b);
}

template <unsigned Bits>
MATH_FUNC
inline bool operator>=(unorm<Bits> a, unorm<Bits> b)
{
    using T = typename unorm<Bits>::value_type;

    return static_cast<T>(a) >= static_cast<T>(b);
}

} // MATH_NAMESPACE
<|endoftext|>


<commit_before>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __BSE_CXX_MODULE_H__
#define __BSE_CXX_MODULE_H__

#include <bse/bsecxxbase.hh>
#include <bse/bseieee754.hh>

namespace Bse {

/* enums/structures mirrored from bseengine.hh */
enum ProcessCost {
  NORMAL,
  CHEAP,
  EXPENSIVE
};
struct JStream {
  const float **values;
  uint          n_connections;
  /* private: */
  uint          jcount; /* reserved */
};
struct IStream {
  const float  *values;
  gboolean      connected;
};
struct OStream {
  float        *values;
  gboolean      connected;
};

class Effect;

class SynthesisModule {
  template<class T, typename P> class ClosureP1; /* 1-argument member function closure */
  BseModule     *intern_module;
public:
  explicit                  SynthesisModule ();
  virtual                  ~SynthesisModule () = 0;
  virtual void              reset           () = 0;
  virtual void              process         (uint n_values) = 0;
  virtual const ProcessCost cost            ();
  inline const IStream&     istream         (uint istream_index) const;
  inline const JStream&     jstream         (uint jstream_index) const;
  inline const OStream&     ostream         (uint ostream_index) const;
  void                      ostream_set     (uint ostream_index,
                                             const float *values);
  const float*              const_values    (float  value);
  inline const uint         mix_freq        () const;
  inline const uint         block_size      () const;
  inline guint64            tick_stamp      ();
  inline BseModule*         engine_module   ();
  static inline int         dtoi            (double d) { return bse_dtoi (d); }
  static inline int         ftoi            (float  f) { return bse_ftoi (f); }
  /* member functions and closures */
  struct Closure {
    virtual void            operator()      (SynthesisModule*) = 0;
    virtual                ~Closure         ()         {}
  };
  /* create a 1-argument member function closure, where C must be derived from SynthesisModule */
  template<class D, class C>
  static Closure*           make_closure    (void    (C::*method) (D*),
                                             const D     &data);
  /* internal */
  void                      set_module      (BseModule *module);
  /* auto_update() trampoline */
public:
  typedef void     (*AutoUpdate)            (BseModule*, gpointer);
  struct AutoUpdateData {
    guint       prop_id;
    double      prop_value;
    /* required by back propagation */
    guint64     tick_stamp;
    GParamSpec *pspec;
    Effect     *effect;
  };
  struct NeedAutoUpdateTag {};
public:
  template<class M, class P, class C> struct Trampoline {
    static void auto_update_accessor (BseModule*, gpointer);
  };
  /* partial trampoline specializations */
  template<class M, class P> struct Trampoline<M,P,NeedAutoUpdateTag> {
    static void auto_update_accessor (BseModule*, gpointer);
  };
  template<class M, class P> struct Trampoline<M,P,void> {
    static void auto_update_accessor (BseModule*, gpointer);
  };
};

#define BSE_TYPE_EFFECT         (BSE_CXX_TYPE_GET_REGISTERED (Bse, Effect))
class EffectBase : public CxxBase {};
class Effect : public EffectBase {
private:
  guint64                   last_module_update;
public:
  /* BseObject functionality */
  explicit                  Effect               ();
  void                      set_property         (guint            prop_id,
                                                  const Value     &value,
                                                  GParamSpec      *pspec);
  void                      get_property         (guint            prop_id,
                                                  Value           &value,
                                                  GParamSpec      *pspec);
  /* BseSource accessors */
  bool          is_prepared()               const { return BSE_SOURCE_PREPARED (gobject()); }
  guint         n_ichannels()               const { return BSE_SOURCE_N_ICHANNELS (gobject()); }
  guint         n_joint_ichannels()         const { return BSE_SOURCE_N_JOINT_ICHANNELS (gobject()); }
  guint         n_ochannels()               const { return BSE_SOURCE_N_OCHANNELS (gobject()); }
  bool          is_joint_ichannel (guint i) const { return BSE_SOURCE_IS_JOINT_ICHANNEL (gobject(), i); }
  guint         ichannels_istream (guint i) const { return BSE_SOURCE_ICHANNEL_ISTREAM (gobject(), i); }
  guint         ichannels_jstream (guint i) const { return BSE_SOURCE_ICHANNEL_JSTREAM (gobject(), i); }
  guint         ochannels_ostream (guint i) const { return BSE_SOURCE_OCHANNEL_OSTREAM (gobject(), i); }
  const gchar*  ichannel_ident    (guint i) const { return BSE_SOURCE_ICHANNEL_IDENT (gobject(), i); }
  const gchar*  ichannel_label    (guint i) const { return BSE_SOURCE_ICHANNEL_LABEL (gobject(), i); }
  const gchar*  ichannel_blurb    (guint i) const { return BSE_SOURCE_ICHANNEL_BLURB (gobject(), i); }
  const gchar*  ochannel_ident    (guint i) const { return BSE_SOURCE_OCHANNEL_IDENT (gobject(), i); }
  const gchar*  ochannel_label    (guint i) const { return BSE_SOURCE_OCHANNEL_LABEL (gobject(), i); }
  const gchar*  ochannel_blurb    (guint i) const { return BSE_SOURCE_OCHANNEL_BLURB (gobject(), i); }
  virtual SynthesisModule*  create_module              (uint             context_handle,
                                                        BseTrans        *trans) = 0;
  virtual SynthesisModule::
  Closure*                  make_module_config_closure () = 0;
  virtual SynthesisModule::
  AutoUpdate                get_module_auto_update     () = 0;
  void                      update_modules             (BseTrans        *trans = NULL);
  guint64                   module_update_tick_stamp   () { return last_module_update; }
  /* prepare & dismiss pre and post invocation hooks */
  virtual void  prepare1()      { /* override this to do something before parent class prepare */ }
  virtual void  prepare2()      { /* override this to do something after parent class prepare */ }
  virtual void  reset1()        { /* override this to do something before parent class dismiss */ }
  virtual void  reset2()        { /* override this to do something after parent class dismiss */ }

  static void               class_init                 (CxxBaseClass    *klass);
protected:
  const BseModuleClass*     create_engine_class        (SynthesisModule *sample_module,
                                                        int              cost = -1,
                                                        int              n_istreams = -1,
                                                        int              n_jstreams = -1,
                                                        int              n_ostreams = -1);
  virtual BseModule*        integrate_engine_module    (uint             context_handle,
                                                        BseTrans        *trans);
  virtual void              dismiss_engine_module      (BseModule       *engine_module,
                                                        guint            context_handle,
                                                        BseTrans        *trans);
  uint                      block_size                 () const;
  uint                      max_block_size             () const;
public: /* FIXME: make this protected as soon as the modules have their own current_musical_tuning() accessor */
  Bse::MusicalTuning    current_musical_tuning     () const;
};
/* implement Bse::Effect and Bse::SynthesisModule methods */
#define BSE_EFFECT_INTEGRATE_MODULE(ObjectType,ModuleType,ParamType)            \
Bse::SynthesisModule*                                                           \
create_module (uint         context_handle,                                     \
               BseTrans    *trans)                                              \
{                                                                               \
  /* check that 'this' is a ObjectType* */                                      \
  (void) const_cast<ObjectType*> (this);                                        \
  /* create a synthesis module */                                               \
  return new ModuleType();                                                      \
}                                                                               \
Bse::SynthesisModule::Closure*                                                  \
make_module_config_closure()                                                    \
{                                                                               \
  return SynthesisModule::make_closure (&ModuleType::config, ParamType (this)); \
}                                                                               \
Bse::SynthesisModule::AutoUpdate                                                \
get_module_auto_update()                                                        \
{                                                                               \
  return SynthesisModule::Trampoline<ModuleType,ParamType,                      \
                  ObjectType::AutoUpdateCategory>::auto_update_accessor;        \
}
template<class M, class P>
void
SynthesisModule::Trampoline<M,P,SynthesisModule::NeedAutoUpdateTag>::
auto_update_accessor (BseModule *bmodule,      /* Engine Thread */
                      gpointer   data)
{
  M *m = static_cast<M*> (BSE_MODULE_GET_USER_DATA (bmodule));
  AutoUpdateData *au = static_cast<AutoUpdateData*> (data);
  typename P::IDType prop_id = static_cast<typename P::IDType> (au->prop_id);
  if (0)        // check M::auto_update() member and prototype
    (void) static_cast<void (M::*) (typename P::IDType, double)> (&M::auto_update);
  m->auto_update (prop_id, au->prop_value);
}
template<class M, class P>
void
SynthesisModule::Trampoline<M,P,void>::
auto_update_accessor (BseModule *bmodule,
                      gpointer   data)
{
}

/* --- implementation details --- */
namespace externC { extern "C" {
extern guint bse_engine_exvar_sample_freq;
extern guint bse_engine_exvar_block_size;
extern guint64 bse_module_tick_stamp (BseModule*);
} }
inline BseModule*
SynthesisModule::engine_module ()
{
  return intern_module;
}
inline const uint
SynthesisModule::mix_freq () const
{
  return externC::bse_engine_exvar_sample_freq;
}
inline const uint
SynthesisModule::block_size () const
{
  return externC::bse_engine_exvar_block_size;
}
inline guint64
SynthesisModule::tick_stamp ()
{
  return externC::bse_module_tick_stamp (engine_module());
}
inline const IStream&
SynthesisModule::istream (uint         istream_index) const
{
  void *istreams = BSE_MODULE_GET_ISTREAMSP (intern_module);
  return reinterpret_cast<IStream*> (istreams)[istream_index];
}
inline const JStream&
SynthesisModule::jstream (uint         jstream_index) const
{
  void *jstreams = BSE_MODULE_GET_JSTREAMSP (intern_module);
  return reinterpret_cast<JStream*> (jstreams)[jstream_index];
}
inline const OStream&
SynthesisModule::ostream (uint         ostream_index) const
{
  void *ostreams = BSE_MODULE_GET_OSTREAMSP (intern_module);
  return reinterpret_cast<OStream*> (ostreams)[ostream_index];
}
template<class T, typename P>
class SynthesisModule::ClosureP1 : public SynthesisModule::Closure {
  typedef void (T::*Member) (P*);
  Member    func;
  P        *data;
public:
  ClosureP1 (void (T::*f) (P*), P *p)
    : func (f), data (p)
  {
    assert_derived_from<T,SynthesisModule>();
  }
  void operator() (SynthesisModule *p)
  {
    T *t = static_cast<T*> (p);
    (t->*func) (data);
  }
  ~ClosureP1 ()
  {
    delete data;
  }
};
template<class D, class C> SynthesisModule::Closure*
SynthesisModule::make_closure (void   (C::*method) (D*),
                               const D    &data)
{
  D *d = new D (data);
  ClosureP1<C,D> *ac = new ClosureP1<C,D> (method, d);
  return ac;
}

} // Bse

#endif /* __BSE_CXX_MODULE_H__ */
<commit_msg>BSE: use bseengine.hh symbols instead of duplicating header bits<commit_after>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __BSE_CXX_MODULE_H__
#define __BSE_CXX_MODULE_H__

#include <bse/bsecxxbase.hh>
#include <bse/bseieee754.hh>
#include <bse/bseengine.hh>

namespace Bse {

/* enums/structures mirrored from bseengine.hh */
enum ProcessCost {
  NORMAL,
  CHEAP,
  EXPENSIVE
};
struct JStream {
  const float **values;
  uint          n_connections;
  /* private: */
  uint          jcount; /* reserved */
};
struct IStream {
  const float  *values;
  gboolean      connected;
};
struct OStream {
  float        *values;
  gboolean      connected;
};

class Effect;

class SynthesisModule {
  template<class T, typename P> class ClosureP1; /* 1-argument member function closure */
  BseModule     *intern_module;
public:
  explicit                  SynthesisModule ();
  virtual                  ~SynthesisModule () = 0;
  virtual void              reset           () = 0;
  virtual void              process         (uint n_values) = 0;
  virtual const ProcessCost cost            ();
  inline const IStream&     istream         (uint istream_index) const;
  inline const JStream&     jstream         (uint jstream_index) const;
  inline const OStream&     ostream         (uint ostream_index) const;
  void                      ostream_set     (uint ostream_index,
                                             const float *values);
  const float*              const_values    (float  value);
  inline const uint         mix_freq        () const;
  inline const uint         block_size      () const;
  inline guint64            tick_stamp      ();
  inline BseModule*         engine_module   ();
  static inline int         dtoi            (double d) { return bse_dtoi (d); }
  static inline int         ftoi            (float  f) { return bse_ftoi (f); }
  /* member functions and closures */
  struct Closure {
    virtual void            operator()      (SynthesisModule*) = 0;
    virtual                ~Closure         ()         {}
  };
  /* create a 1-argument member function closure, where C must be derived from SynthesisModule */
  template<class D, class C>
  static Closure*           make_closure    (void    (C::*method) (D*),
                                             const D     &data);
  /* internal */
  void                      set_module      (BseModule *module);
  /* auto_update() trampoline */
public:
  typedef void     (*AutoUpdate)            (BseModule*, gpointer);
  struct AutoUpdateData {
    guint       prop_id;
    double      prop_value;
    /* required by back propagation */
    guint64     tick_stamp;
    GParamSpec *pspec;
    Effect     *effect;
  };
  struct NeedAutoUpdateTag {};
public:
  template<class M, class P, class C> struct Trampoline {
    static void auto_update_accessor (BseModule*, gpointer);
  };
  /* partial trampoline specializations */
  template<class M, class P> struct Trampoline<M,P,NeedAutoUpdateTag> {
    static void auto_update_accessor (BseModule*, gpointer);
  };
  template<class M, class P> struct Trampoline<M,P,void> {
    static void auto_update_accessor (BseModule*, gpointer);
  };
};

#define BSE_TYPE_EFFECT         (BSE_CXX_TYPE_GET_REGISTERED (Bse, Effect))
class EffectBase : public CxxBase {};
class Effect : public EffectBase {
private:
  guint64                   last_module_update;
public:
  /* BseObject functionality */
  explicit                  Effect               ();
  void                      set_property         (guint            prop_id,
                                                  const Value     &value,
                                                  GParamSpec      *pspec);
  void                      get_property         (guint            prop_id,
                                                  Value           &value,
                                                  GParamSpec      *pspec);
  /* BseSource accessors */
  bool          is_prepared()               const { return BSE_SOURCE_PREPARED (gobject()); }
  guint         n_ichannels()               const { return BSE_SOURCE_N_ICHANNELS (gobject()); }
  guint         n_joint_ichannels()         const { return BSE_SOURCE_N_JOINT_ICHANNELS (gobject()); }
  guint         n_ochannels()               const { return BSE_SOURCE_N_OCHANNELS (gobject()); }
  bool          is_joint_ichannel (guint i) const { return BSE_SOURCE_IS_JOINT_ICHANNEL (gobject(), i); }
  guint         ichannels_istream (guint i) const { return BSE_SOURCE_ICHANNEL_ISTREAM (gobject(), i); }
  guint         ichannels_jstream (guint i) const { return BSE_SOURCE_ICHANNEL_JSTREAM (gobject(), i); }
  guint         ochannels_ostream (guint i) const { return BSE_SOURCE_OCHANNEL_OSTREAM (gobject(), i); }
  const gchar*  ichannel_ident    (guint i) const { return BSE_SOURCE_ICHANNEL_IDENT (gobject(), i); }
  const gchar*  ichannel_label    (guint i) const { return BSE_SOURCE_ICHANNEL_LABEL (gobject(), i); }
  const gchar*  ichannel_blurb    (guint i) const { return BSE_SOURCE_ICHANNEL_BLURB (gobject(), i); }
  const gchar*  ochannel_ident    (guint i) const { return BSE_SOURCE_OCHANNEL_IDENT (gobject(), i); }
  const gchar*  ochannel_label    (guint i) const { return BSE_SOURCE_OCHANNEL_LABEL (gobject(), i); }
  const gchar*  ochannel_blurb    (guint i) const { return BSE_SOURCE_OCHANNEL_BLURB (gobject(), i); }
  virtual SynthesisModule*  create_module              (uint             context_handle,
                                                        BseTrans        *trans) = 0;
  virtual SynthesisModule::
  Closure*                  make_module_config_closure () = 0;
  virtual SynthesisModule::
  AutoUpdate                get_module_auto_update     () = 0;
  void                      update_modules             (BseTrans        *trans = NULL);
  guint64                   module_update_tick_stamp   () { return last_module_update; }
  /* prepare & dismiss pre and post invocation hooks */
  virtual void  prepare1()      { /* override this to do something before parent class prepare */ }
  virtual void  prepare2()      { /* override this to do something after parent class prepare */ }
  virtual void  reset1()        { /* override this to do something before parent class dismiss */ }
  virtual void  reset2()        { /* override this to do something after parent class dismiss */ }

  static void               class_init                 (CxxBaseClass    *klass);
protected:
  const BseModuleClass*     create_engine_class        (SynthesisModule *sample_module,
                                                        int              cost = -1,
                                                        int              n_istreams = -1,
                                                        int              n_jstreams = -1,
                                                        int              n_ostreams = -1);
  virtual BseModule*        integrate_engine_module    (uint             context_handle,
                                                        BseTrans        *trans);
  virtual void              dismiss_engine_module      (BseModule       *engine_module,
                                                        guint            context_handle,
                                                        BseTrans        *trans);
  uint                      block_size                 () const;
  uint                      max_block_size             () const;
public: /* FIXME: make this protected as soon as the modules have their own current_musical_tuning() accessor */
  Bse::MusicalTuning    current_musical_tuning     () const;
};
/* implement Bse::Effect and Bse::SynthesisModule methods */
#define BSE_EFFECT_INTEGRATE_MODULE(ObjectType,ModuleType,ParamType)            \
Bse::SynthesisModule*                                                           \
create_module (uint         context_handle,                                     \
               BseTrans    *trans)                                              \
{                                                                               \
  /* check that 'this' is a ObjectType* */                                      \
  (void) const_cast<ObjectType*> (this);                                        \
  /* create a synthesis module */                                               \
  return new ModuleType();                                                      \
}                                                                               \
Bse::SynthesisModule::Closure*                                                  \
make_module_config_closure()                                                    \
{                                                                               \
  return SynthesisModule::make_closure (&ModuleType::config, ParamType (this)); \
}                                                                               \
Bse::SynthesisModule::AutoUpdate                                                \
get_module_auto_update()                                                        \
{                                                                               \
  return SynthesisModule::Trampoline<ModuleType,ParamType,                      \
                  ObjectType::AutoUpdateCategory>::auto_update_accessor;        \
}
template<class M, class P>
void
SynthesisModule::Trampoline<M,P,SynthesisModule::NeedAutoUpdateTag>::
auto_update_accessor (BseModule *bmodule,      /* Engine Thread */
                      gpointer   data)
{
  M *m = static_cast<M*> (BSE_MODULE_GET_USER_DATA (bmodule));
  AutoUpdateData *au = static_cast<AutoUpdateData*> (data);
  typename P::IDType prop_id = static_cast<typename P::IDType> (au->prop_id);
  if (0)        // check M::auto_update() member and prototype
    (void) static_cast<void (M::*) (typename P::IDType, double)> (&M::auto_update);
  m->auto_update (prop_id, au->prop_value);
}
template<class M, class P>
void
SynthesisModule::Trampoline<M,P,void>::
auto_update_accessor (BseModule *bmodule,
                      gpointer   data)
{
}

/* --- implementation details --- */
inline BseModule*
SynthesisModule::engine_module ()
{
  return intern_module;
}
inline const uint
SynthesisModule::mix_freq () const
{
  return bse_engine_sample_freq();
}
inline const uint
SynthesisModule::block_size () const
{
  return bse_engine_block_size();
}
inline guint64
SynthesisModule::tick_stamp ()
{
  return bse_module_tick_stamp (engine_module());
}
inline const IStream&
SynthesisModule::istream (uint         istream_index) const
{
  void *istreams = BSE_MODULE_GET_ISTREAMSP (intern_module);
  return reinterpret_cast<IStream*> (istreams)[istream_index];
}
inline const JStream&
SynthesisModule::jstream (uint         jstream_index) const
{
  void *jstreams = BSE_MODULE_GET_JSTREAMSP (intern_module);
  return reinterpret_cast<JStream*> (jstreams)[jstream_index];
}
inline const OStream&
SynthesisModule::ostream (uint         ostream_index) const
{
  void *ostreams = BSE_MODULE_GET_OSTREAMSP (intern_module);
  return reinterpret_cast<OStream*> (ostreams)[ostream_index];
}
template<class T, typename P>
class SynthesisModule::ClosureP1 : public SynthesisModule::Closure {
  typedef void (T::*Member) (P*);
  Member    func;
  P        *data;
public:
  ClosureP1 (void (T::*f) (P*), P *p)
    : func (f), data (p)
  {
    assert_derived_from<T,SynthesisModule>();
  }
  void operator() (SynthesisModule *p)
  {
    T *t = static_cast<T*> (p);
    (t->*func) (data);
  }
  ~ClosureP1 ()
  {
    delete data;
  }
};
template<class D, class C> SynthesisModule::Closure*
SynthesisModule::make_closure (void   (C::*method) (D*),
                               const D    &data)
{
  D *d = new D (data);
  ClosureP1<C,D> *ac = new ClosureP1<C,D> (method, d);
  return ac;
}

} // Bse

#endif /* __BSE_CXX_MODULE_H__ */
<|endoftext|>


<commit_before><commit_msg>sfx2: PVS-Studio V595 'm_pResMgr' pointer could be null<commit_after><|endoftext|>


<commit_before>//
//  partlistvisitor.cpp
//  libmusicxml2
//
//  Created by Arshia Cont on 05/01/17.
//
//

#include <algorithm>

#include "partlistvisitor.h"

#include "rational.h"
#include "xml_tree_browser.h"
#include "tree_browser.h"

using namespace std;

namespace MusicXML2
{
    partlistvisitor::partlistvisitor() : fPartGroupIncrementer(0), staffCreatorCounter(1)
    {
    }

    partGroup* partlistvisitor::find_first_of_partID_inGroup(std::string partID)
    {
        // search if this part ID exists in any grouping
        // Guido Limitation: One \accol tag per staff ONLY (for nested definitions)
        // IDEA: Treat the FIRST occurence of partID in grouping and get rid of it.
        std::map<int, partGroup>::iterator partGroupIt;
        for (partGroupIt=fPartGroups.begin();
             partGroupIt != fPartGroups.end();
             partGroupIt++)
        {
            if (partGroupIt->second.visited == false) {
                if (std::find(partGroupIt->second.partIDs.begin()
                              , partGroupIt->second.partIDs.end(),
                              partID) != partGroupIt->second.partIDs.end() )
                {
                    // this partID is in group number partGroupIt->first
                    //cerr << "\t ID found in group " << partGroupIt->first <<" "<<endl;
                    break;

                }
            }
        }

        if (partGroupIt != fPartGroups.end())
        {
            return &partGroupIt->second;
        }

        return NULL;
    }

    void partlistvisitor::partID2range(partGroup &pGroup)
    {
        std::vector<int> staves;
        for (size_t i=0; i<pGroup.partIDs.size();i++)
        {
            staves.push_back(part2staffmap[pGroup.partIDs[i]]);
        }
		if (staves.empty()) return;

        std::vector<int>::iterator rangeEnd = std::max_element(staves.begin(), staves.end());
        std::vector<int>::iterator rangeBegin = std::min_element(staves.begin(), staves.begin());

        stringstream rangeStream;
        rangeStream << "\"" << (*rangeBegin) << "-" << (*rangeEnd) << "\"";
        pGroup.guidoRange = rangeStream.str();
        pGroup.guidoRangeStart = *rangeBegin;
        pGroup.guidoRangeStop = *rangeEnd;
    }

    bool partlistvisitor::checkLonelyBarFormat(int staffID)
    {
        std::map<int, partGroup>::iterator partGroupIt;
        for (partGroupIt=fPartGroups.begin();
             partGroupIt != fPartGroups.end();
             partGroupIt++)
        {
            if (partGroupIt->second.barlineGrouping == true)
            {
                // see if this staff is in range
                if ( (staffID>= partGroupIt->second.guidoRangeStart)&&(staffID<=partGroupIt->second.guidoRangeStop))
                {
                    return false;
                }
            }
        }

        return true;
    }

    /// Visitors

    void partlistvisitor::visitStart ( S_part_group& elt )
    {
        int partGroupNumber = elt->getAttributeIntValue("number", 0);
        /// IMPORTANT NOTE: the number attribute is NOT sequential and can be repeated! So we need to do further book-keeping.
        std::string partGroupType = elt->getAttributeValue("type");

        if (partGroupType=="start")
        {
            int groupIndex = fPartGroupIncrementer;
            fPartGroups[groupIndex].xmlGroupNumber = partGroupNumber;
            if (elt->getValue(k_group_symbol)=="bracket")
            {
                fPartGroups[groupIndex].bracket = true;
            } else
                fPartGroups[groupIndex].bracket = false;

            if (elt->getValue(k_group_barline)=="yes")
            {
                fPartGroups[groupIndex].barlineGrouping = true;
            } else
                fPartGroups[groupIndex].barlineGrouping = false;

            // Add optional names
            fPartGroups[groupIndex].fGroupName = elt->getValue(k_group_name);
            fPartGroups[groupIndex].visited = false;

            fCurrentPartGroupIndex.push_back(groupIndex);
            fPartGroupIncrementer++;
            //cerr << "Started group " << partGroupNumber << " index " << groupIndex<<" (" << fCurrentPartGroupIndex.size() << ")" << endl;
        }else
            if (partGroupType=="stop")
            {
                // Erase the INDEX whose xmlGroupNumber is equal to partGroupNumber
                std::vector<int>::iterator ito;
                for (ito = fCurrentPartGroupIndex.begin(); ito < fCurrentPartGroupIndex.end(); ito++)
                {
                    if (fPartGroups[*ito].xmlGroupNumber == partGroupNumber)
                        break;
                }

                // Do Erase
                if (ito != fCurrentPartGroupIndex.end())
                {
                    // calculate Guido Range and set
                    partID2range(fPartGroups[*ito]);
                    fCurrentPartGroupIndex.erase(ito);
                }else
                    cerr << "Something is really wrong in S_PART_GROUP visitor!" << endl;
            }
    }

    void partlistvisitor::visitStart( S_score_part& elt)
    {
        std::string PartID = elt->getAttributeValue("id");
        part2staffmap[PartID] = staffCreatorCounter;
        staffCreatorCounter++;

        fPartHeaders[PartID].fPartName = elt->getValue(k_part_name);
        fPartHeaders[PartID].fPartNameAbbr = elt->getValue(k_part_abbreviation);

        // add groupings if any
        if (fCurrentPartGroupIndex.size())
        {
            for (size_t ind=0; ind < fCurrentPartGroupIndex.size(); ind++)
            {
                fPartGroups[fCurrentPartGroupIndex[ind]].partIDs.push_back(PartID);
            }
        }
    }

}
<commit_msg>xml2guido: Fix accolade and barformat staff ranges<commit_after>//
//  partlistvisitor.cpp
//  libmusicxml2
//
//  Created by Arshia Cont on 05/01/17.
//
//

#include <algorithm>

#include "partlistvisitor.h"

#include "rational.h"
#include "xml_tree_browser.h"
#include "tree_browser.h"

using namespace std;

namespace MusicXML2
{
    partlistvisitor::partlistvisitor() : fPartGroupIncrementer(0), staffCreatorCounter(1)
    {
    }

    partGroup* partlistvisitor::find_first_of_partID_inGroup(std::string partID)
    {
        // search if this part ID exists in any grouping
        // Guido Limitation: One \accol tag per staff ONLY (for nested definitions)
        // IDEA: Treat the FIRST occurence of partID in grouping and get rid of it.
        std::map<int, partGroup>::iterator partGroupIt;
        for (partGroupIt=fPartGroups.begin();
             partGroupIt != fPartGroups.end();
             partGroupIt++)
        {
            if (partGroupIt->second.visited == false) {
                if (std::find(partGroupIt->second.partIDs.begin()
                              , partGroupIt->second.partIDs.end(),
                              partID) != partGroupIt->second.partIDs.end() )
                {
                    // this partID is in group number partGroupIt->first
                    //cerr << "\t ID found in group " << partGroupIt->first <<" "<<endl;
                    break;

                }
            }
        }

        if (partGroupIt != fPartGroups.end())
        {
            return &partGroupIt->second;
        }

        return NULL;
    }

    void partlistvisitor::partID2range(partGroup &pGroup)
    {
        std::vector<int> staves;
        for (size_t i=0; i<pGroup.partIDs.size();i++)
        {
            staves.push_back(part2staffmap[pGroup.partIDs[i]]);
        }
		if (staves.empty()) return;

        std::vector<int>::iterator rangeEnd = std::max_element(staves.begin(), staves.end());
        std::vector<int>::iterator rangeBegin = std::min_element(staves.begin(), staves.begin());

        stringstream rangeStream;
        rangeStream << "\"" << (*rangeBegin)+1 << "-" << (*rangeEnd)+1 << "\"";
        pGroup.guidoRange = rangeStream.str();
        pGroup.guidoRangeStart = *rangeBegin +1;
        pGroup.guidoRangeStop = *rangeEnd +1;
    }

    bool partlistvisitor::checkLonelyBarFormat(int staffID)
    {
        std::map<int, partGroup>::iterator partGroupIt;
        for (partGroupIt=fPartGroups.begin();
             partGroupIt != fPartGroups.end();
             partGroupIt++)
        {
            if (partGroupIt->second.barlineGrouping == true)
            {
                // see if this staff is in range
                if ( (staffID>= partGroupIt->second.guidoRangeStart)&&(staffID<=partGroupIt->second.guidoRangeStop))
                {
                    return false;
                }
            }
        }

        return true;
    }

    /// Visitors

    void partlistvisitor::visitStart ( S_part_group& elt )
    {
        int partGroupNumber = elt->getAttributeIntValue("number", 0);
        /// IMPORTANT NOTE: the number attribute is NOT sequential and can be repeated! So we need to do further book-keeping.
        std::string partGroupType = elt->getAttributeValue("type");

        if (partGroupType=="start")
        {
            int groupIndex = fPartGroupIncrementer;
            fPartGroups[groupIndex].xmlGroupNumber = partGroupNumber;
            if (elt->getValue(k_group_symbol)=="bracket")
            {
                fPartGroups[groupIndex].bracket = true;
            } else
                fPartGroups[groupIndex].bracket = false;

            if (elt->getValue(k_group_barline)=="yes")
            {
                fPartGroups[groupIndex].barlineGrouping = true;
            } else
                fPartGroups[groupIndex].barlineGrouping = false;

            // Add optional names
            fPartGroups[groupIndex].fGroupName = elt->getValue(k_group_name);
            fPartGroups[groupIndex].visited = false;

            fCurrentPartGroupIndex.push_back(groupIndex);
            fPartGroupIncrementer++;
            //cerr << "Started group " << partGroupNumber << " index " << groupIndex<<" (" << fCurrentPartGroupIndex.size() << ")" << endl;
        }else
            if (partGroupType=="stop")
            {
                // Erase the INDEX whose xmlGroupNumber is equal to partGroupNumber
                std::vector<int>::iterator ito;
                for (ito = fCurrentPartGroupIndex.begin(); ito < fCurrentPartGroupIndex.end(); ito++)
                {
                    if (fPartGroups[*ito].xmlGroupNumber == partGroupNumber)
                        break;
                }

                // Do Erase
                if (ito != fCurrentPartGroupIndex.end())
                {
                    // calculate Guido Range and set
                    partID2range(fPartGroups[*ito]);
                    fCurrentPartGroupIndex.erase(ito);
                }else
                    cerr << "Something is really wrong in S_PART_GROUP visitor!" << endl;
            }
    }

    void partlistvisitor::visitStart( S_score_part& elt)
    {
        std::string PartID = elt->getAttributeValue("id");
        part2staffmap[PartID] = staffCreatorCounter;
        staffCreatorCounter++;

        fPartHeaders[PartID].fPartName = elt->getValue(k_part_name);
        fPartHeaders[PartID].fPartNameAbbr = elt->getValue(k_part_abbreviation);

        // add groupings if any
        if (fCurrentPartGroupIndex.size())
        {
            for (size_t ind=0; ind < fCurrentPartGroupIndex.size(); ind++)
            {
                fPartGroups[fCurrentPartGroupIndex[ind]].partIDs.push_back(PartID);
            }
        }
    }

}
<|endoftext|>


<commit_before>/******************************************************************************
 * resourcegroupmanager_bind.cpp - bindings for Ogre::ResourceGroupManager
 ******************************************************************************
 * This file is part of
 *     __ __              _
 *    / // /_____ ____   (_)
 *   / // // ___// __ \ / /
 *  / // // /__ / /_/ // /
 * /_//_/ \___/ \____//_/
 *
 * Low Level C Ogre Interface (llcoi)
 *
 * See http://code.google.com/p/llcoi/ for more information.
 *
 * Copyright (c) 2011, Llcoi Team
 *
 * License: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/
#include "ogre_interface.h"

#include <OgreRoot.h>
#include <OgreConfigFile.h>
#include <OgreResourceManager.h>
#include <OgreResourceGroupManager.h>
#include <OgreResource.h>

void setup_resources(const char* resources_cfg)
{
    // set up resources
    // Load resource paths from config file
    Ogre::ConfigFile cf;
    cf.load(resources_cfg);

    // Go through all sections & settings in the file
    Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

    Ogre::String secName, typeName, archName;
    while (seci.hasMoreElements())
    {
        secName = seci.peekNextKey();
        Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
        Ogre::ConfigFile::SettingsMultiMap::iterator i;
        for (i = settings->begin(); i != settings->end(); ++i)
        {
            typeName = i->first;
            archName = i->second;
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
                archName, typeName, secName);
        }
    }
}

// Ogre::ResourceGroupManager::addResourceLocation(std::string const&, std::string const&, std::string const&, bool)
void add_resource_location(const char* location, const char* type, const char* group)
{
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(location, type, group);
}

// Ogre::ResourceGroupManager::initialiseAllResourceGroups()
void initialise_all_resourcegroups()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
}

/*
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME
Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME
Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME
Ogre::ResourceGroupManager::RESOURCE_SYSTEM_NUM_REFERENCE_COUNTS
Ogre::ResourceGroupManager::ResourceDeclaration
Ogre::ResourceGroupManager::ResourceLocation
Ogre::ResourceGroupManager::ResourceGroupManager()
Ogre::ResourceGroupManager::~ResourceGroupManager()
Ogre::ResourceGroupManager::createResourceGroup(std::string const&, bool)
Ogre::ResourceGroupManager::initialiseResourceGroup(std::string const&)
Ogre::ResourceGroupManager::prepareResourceGroup(std::string const&, bool, bool)
Ogre::ResourceGroupManager::loadResourceGroup(std::string const&, bool, bool)
Ogre::ResourceGroupManager::unloadResourceGroup(std::string const&, bool)
Ogre::ResourceGroupManager::unloadUnreferencedResourcesInGroup(std::string const&, bool)
Ogre::ResourceGroupManager::clearResourceGroup(std::string const&)
Ogre::ResourceGroupManager::destroyResourceGroup(std::string const&)
Ogre::ResourceGroupManager::isResourceGroupInitialised(std::string const&)
Ogre::ResourceGroupManager::isResourceGroupLoaded(std::string const&)
Ogre::ResourceGroupManager::resourceGroupExists(std::string const&)
Ogre::ResourceGroupManager::removeResourceLocation(std::string const&, std::string const&)
Ogre::ResourceGroupManager::resourceLocationExists(std::string const&, std::string const&)
Ogre::ResourceGroupManager::declareResource(std::string const&, std::string const&, std::string const&, std::map<std::string, std::string, std::less<std::string>, Ogre::STLAllocator<std::pair<std::string const, std::string>, Ogre::CategorisedAllocPolicy<(Ogre::MemoryCategory)0> > > const&)
Ogre::ResourceGroupManager::declareResource(std::string const&, std::string const&, std::string const&, Ogre::ManualResourceLoader*, std::map<std::string, std::string, std::less<std::string>, Ogre::STLAllocator<std::pair<std::string const, std::string>, Ogre::CategorisedAllocPolicy<(Ogre::MemoryCategory)0> > > const&)
Ogre::ResourceGroupManager::undeclareResource(std::string const&, std::string const&)
Ogre::ResourceGroupManager::openResource(std::string const&, std::string const&, bool, Ogre::Resource*)
Ogre::ResourceGroupManager::openResources(std::string const&, std::string const&)
Ogre::ResourceGroupManager::listResourceNames(std::string const&, bool)
Ogre::ResourceGroupManager::listResourceFileInfo(std::string const&, bool)
Ogre::ResourceGroupManager::findResourceNames(std::string const&, std::string const&, bool)
Ogre::ResourceGroupManager::resourceExists(std::string const&, std::string const&)
Ogre::ResourceGroupManager::resourceExists(Ogre::ResourceGroupManager::ResourceGroup*, std::string const&)
Ogre::ResourceGroupManager::resourceExistsInAnyGroup(std::string const&)
Ogre::ResourceGroupManager::findGroupContainingResource(std::string const&)
Ogre::ResourceGroupManager::findResourceFileInfo(std::string const&, std::string const&, bool)
Ogre::ResourceGroupManager::resourceModifiedTime(std::string const&, std::string const&)
Ogre::ResourceGroupManager::listResourceLocations(std::string const&)
Ogre::ResourceGroupManager::findResourceLocation(std::string const&, std::string const&)
Ogre::ResourceGroupManager::resourceModifiedTime(Ogre::ResourceGroupManager::ResourceGroup*, std::string const&)
Ogre::ResourceGroupManager::createResource(std::string const&, std::string const&, bool, std::string const&)
Ogre::ResourceGroupManager::deleteResource(std::string const&, std::string const&, std::string const&)
Ogre::ResourceGroupManager::deleteMatchingResources(std::string const&, std::string const&, std::string const&)
Ogre::ResourceGroupManager::addResourceGroupListener(Ogre::ResourceGroupListener*)
Ogre::ResourceGroupManager::removeResourceGroupListener(Ogre::ResourceGroupListener*)
Ogre::ResourceGroupManager::setWorldResourceGroupName(std::string const&)
Ogre::ResourceGroupManager::getWorldResourceGroupName() const
Ogre::ResourceGroupManager::linkWorldGeometryToResourceGroup(std::string const&, std::string const&, Ogre::SceneManager*)
Ogre::ResourceGroupManager::unlinkWorldGeometryFromResourceGroup(std::string const&)
Ogre::ResourceGroupManager::isResourceGroupInGlobalPool(std::string const&)
Ogre::ResourceGroupManager::shutdownAll()
Ogre::ResourceGroupManager::_registerResourceManager(std::string const&, Ogre::ResourceManager*)
Ogre::ResourceGroupManager::_unregisterResourceManager(std::string const&)
Ogre::ResourceGroupManager::getResourceManagerIterator()
Ogre::ResourceGroupManager::_registerScriptLoader(Ogre::ScriptLoader*)
Ogre::ResourceGroupManager::_unregisterScriptLoader(Ogre::ScriptLoader*)
Ogre::ResourceGroupManager::_findScriptLoader(std::string const&)
Ogre::ResourceGroupManager::_getResourceManager(std::string const&)
Ogre::ResourceGroupManager::_notifyResourceCreated(Ogre::SharedPtr<Ogre::Resource>&)
Ogre::ResourceGroupManager::_notifyResourceRemoved(Ogre::SharedPtr<Ogre::Resource>&)
Ogre::ResourceGroupManager::_notifyResourceGroupChanged(std::string const&, Ogre::Resource*)
Ogre::ResourceGroupManager::_notifyAllResourcesRemoved(Ogre::ResourceManager*)
Ogre::ResourceGroupManager::_notifyWorldGeometryStageStarted(std::string const&)
Ogre::ResourceGroupManager::_notifyWorldGeometryStageEnded()
Ogre::ResourceGroupManager::getResourceGroups()
Ogre::ResourceGroupManager::getResourceDeclarationList(std::string const&)
Ogre::ResourceGroupManager::getResourceLocationList(std::string const&)
Ogre::ResourceGroupManager::setLoadingListener(Ogre::ResourceLoadingListener*)
Ogre::ResourceGroupManager::getLoadingListener()
Ogre::ResourceGroupManager::getSingleton()
Ogre::ResourceGroupManager::getSingletonPtr()
Ogre::ResourceGroupManager::ResourceDeclaration::~ResourceDeclaration()
Ogre::ResourceGroupManager::ResourceDeclaration::operator=(Ogre::ResourceGroupManager::ResourceDeclaration const&)
Ogre::ResourceGroupManager::ResourceDeclaration::ResourceDeclaration(Ogre::ResourceGroupManager::ResourceDeclaration const&)
Ogre::ResourceGroupManager::ResourceDeclaration::ResourceDeclaration()
Ogre::ResourceGroupManager::ResourceLocation::~ResourceLocation()
Ogre::ResourceGroupManager::ResourceLocation::operator=(Ogre::ResourceGroupManager::ResourceLocation const&)
Ogre::ResourceGroupManager::ResourceLocation::ResourceLocation(Ogre::ResourceGroupManager::ResourceLocation const&)
Ogre::ResourceGroupManager::ResourceLocation::ResourceLocation()
Ogre::ResourceGroupManager::ResourceGroup::~ResourceGroup()
Ogre::ResourceGroupManager::ResourceGroup::ResourceGroup()
Ogre::ResourceGroupManager::ResourceGroup::addToIndex(std::string const&, Ogre::Archive*)
Ogre::ResourceGroupManager::ResourceGroup::removeFromIndex(std::string const&, Ogre::Archive*)
Ogre::ResourceGroupManager::ResourceGroup::removeFromIndex(Ogre::Archive*)
*/
<commit_msg>added access to some constants.<commit_after>/******************************************************************************
 * resourcegroupmanager_bind.cpp - bindings for Ogre::ResourceGroupManager
 ******************************************************************************
 * This file is part of
 *     __ __              _
 *    / // /_____ ____   (_)
 *   / // // ___// __ \ / /
 *  / // // /__ / /_/ // /
 * /_//_/ \___/ \____//_/
 *
 * Low Level C Ogre Interface (llcoi)
 *
 * See http://code.google.com/p/llcoi/ for more information.
 *
 * Copyright (c) 2011, Llcoi Team
 *
 * License: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/
#include "ogre_interface.h"

#include <OgreRoot.h>
#include <OgreConfigFile.h>
#include <OgreResourceManager.h>
#include <OgreResourceGroupManager.h>
#include <OgreResource.h>

void setup_resources(const char* resources_cfg)
{
    // set up resources
    // Load resource paths from config file
    Ogre::ConfigFile cf;
    cf.load(resources_cfg);

    // Go through all sections & settings in the file
    Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

    Ogre::String secName, typeName, archName;
    while (seci.hasMoreElements())
    {
        secName = seci.peekNextKey();
        Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
        Ogre::ConfigFile::SettingsMultiMap::iterator i;
        for (i = settings->begin(); i != settings->end(); ++i)
        {
            typeName = i->first;
            archName = i->second;
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
                archName, typeName, secName);
        }
    }
}

// Ogre::ResourceGroupManager::addResourceLocation(std::string const&, std::string const&, std::string const&, bool)
void add_resource_location(const char* location, const char* type, const char* group)
{
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(location, type, group);
}

// Ogre::ResourceGroupManager::initialiseAllResourceGroups()
void initialise_all_resourcegroups()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
}

const char * resourcegroupmanager_DEFAULT_RESOURCE_GROUP_NAME()
{
    return Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME.c_str();
}

const char * resourcegroupmanager_INTERNAL_RESOURCE_GROUP_NAME()
{
    return Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME.c_str();
}

const char * resourcegroupmanager_AUTODETECT_RESOURCE_GROUP_NAME()
{
    return Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME.c_str();
}

size_t resourcegroupmanager_RESOURCE_SYSTEM_NUM_REFERENCE_COUNTS()
{
    return Ogre::ResourceGroupManager::RESOURCE_SYSTEM_NUM_REFERENCE_COUNTS;
}

/*
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME
Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME
Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME
Ogre::ResourceGroupManager::RESOURCE_SYSTEM_NUM_REFERENCE_COUNTS
Ogre::ResourceGroupManager::ResourceDeclaration
Ogre::ResourceGroupManager::ResourceLocation
Ogre::ResourceGroupManager::ResourceGroupManager()
Ogre::ResourceGroupManager::~ResourceGroupManager()
Ogre::ResourceGroupManager::createResourceGroup(std::string const&, bool)
Ogre::ResourceGroupManager::initialiseResourceGroup(std::string const&)
Ogre::ResourceGroupManager::prepareResourceGroup(std::string const&, bool, bool)
Ogre::ResourceGroupManager::loadResourceGroup(std::string const&, bool, bool)
Ogre::ResourceGroupManager::unloadResourceGroup(std::string const&, bool)
Ogre::ResourceGroupManager::unloadUnreferencedResourcesInGroup(std::string const&, bool)
Ogre::ResourceGroupManager::clearResourceGroup(std::string const&)
Ogre::ResourceGroupManager::destroyResourceGroup(std::string const&)
Ogre::ResourceGroupManager::isResourceGroupInitialised(std::string const&)
Ogre::ResourceGroupManager::isResourceGroupLoaded(std::string const&)
Ogre::ResourceGroupManager::resourceGroupExists(std::string const&)
Ogre::ResourceGroupManager::removeResourceLocation(std::string const&, std::string const&)
Ogre::ResourceGroupManager::resourceLocationExists(std::string const&, std::string const&)
Ogre::ResourceGroupManager::declareResource(std::string const&, std::string const&, std::string const&, std::map<std::string, std::string, std::less<std::string>, Ogre::STLAllocator<std::pair<std::string const, std::string>, Ogre::CategorisedAllocPolicy<(Ogre::MemoryCategory)0> > > const&)
Ogre::ResourceGroupManager::declareResource(std::string const&, std::string const&, std::string const&, Ogre::ManualResourceLoader*, std::map<std::string, std::string, std::less<std::string>, Ogre::STLAllocator<std::pair<std::string const, std::string>, Ogre::CategorisedAllocPolicy<(Ogre::MemoryCategory)0> > > const&)
Ogre::ResourceGroupManager::undeclareResource(std::string const&, std::string const&)
Ogre::ResourceGroupManager::openResource(std::string const&, std::string const&, bool, Ogre::Resource*)
Ogre::ResourceGroupManager::openResources(std::string const&, std::string const&)
Ogre::ResourceGroupManager::listResourceNames(std::string const&, bool)
Ogre::ResourceGroupManager::listResourceFileInfo(std::string const&, bool)
Ogre::ResourceGroupManager::findResourceNames(std::string const&, std::string const&, bool)
Ogre::ResourceGroupManager::resourceExists(std::string const&, std::string const&)
Ogre::ResourceGroupManager::resourceExists(Ogre::ResourceGroupManager::ResourceGroup*, std::string const&)
Ogre::ResourceGroupManager::resourceExistsInAnyGroup(std::string const&)
Ogre::ResourceGroupManager::findGroupContainingResource(std::string const&)
Ogre::ResourceGroupManager::findResourceFileInfo(std::string const&, std::string const&, bool)
Ogre::ResourceGroupManager::resourceModifiedTime(std::string const&, std::string const&)
Ogre::ResourceGroupManager::listResourceLocations(std::string const&)
Ogre::ResourceGroupManager::findResourceLocation(std::string const&, std::string const&)
Ogre::ResourceGroupManager::resourceModifiedTime(Ogre::ResourceGroupManager::ResourceGroup*, std::string const&)
Ogre::ResourceGroupManager::createResource(std::string const&, std::string const&, bool, std::string const&)
Ogre::ResourceGroupManager::deleteResource(std::string const&, std::string const&, std::string const&)
Ogre::ResourceGroupManager::deleteMatchingResources(std::string const&, std::string const&, std::string const&)
Ogre::ResourceGroupManager::addResourceGroupListener(Ogre::ResourceGroupListener*)
Ogre::ResourceGroupManager::removeResourceGroupListener(Ogre::ResourceGroupListener*)
Ogre::ResourceGroupManager::setWorldResourceGroupName(std::string const&)
Ogre::ResourceGroupManager::getWorldResourceGroupName() const
Ogre::ResourceGroupManager::linkWorldGeometryToResourceGroup(std::string const&, std::string const&, Ogre::SceneManager*)
Ogre::ResourceGroupManager::unlinkWorldGeometryFromResourceGroup(std::string const&)
Ogre::ResourceGroupManager::isResourceGroupInGlobalPool(std::string const&)
Ogre::ResourceGroupManager::shutdownAll()
Ogre::ResourceGroupManager::_registerResourceManager(std::string const&, Ogre::ResourceManager*)
Ogre::ResourceGroupManager::_unregisterResourceManager(std::string const&)
Ogre::ResourceGroupManager::getResourceManagerIterator()
Ogre::ResourceGroupManager::_registerScriptLoader(Ogre::ScriptLoader*)
Ogre::ResourceGroupManager::_unregisterScriptLoader(Ogre::ScriptLoader*)
Ogre::ResourceGroupManager::_findScriptLoader(std::string const&)
Ogre::ResourceGroupManager::_getResourceManager(std::string const&)
Ogre::ResourceGroupManager::_notifyResourceCreated(Ogre::SharedPtr<Ogre::Resource>&)
Ogre::ResourceGroupManager::_notifyResourceRemoved(Ogre::SharedPtr<Ogre::Resource>&)
Ogre::ResourceGroupManager::_notifyResourceGroupChanged(std::string const&, Ogre::Resource*)
Ogre::ResourceGroupManager::_notifyAllResourcesRemoved(Ogre::ResourceManager*)
Ogre::ResourceGroupManager::_notifyWorldGeometryStageStarted(std::string const&)
Ogre::ResourceGroupManager::_notifyWorldGeometryStageEnded()
Ogre::ResourceGroupManager::getResourceGroups()
Ogre::ResourceGroupManager::getResourceDeclarationList(std::string const&)
Ogre::ResourceGroupManager::getResourceLocationList(std::string const&)
Ogre::ResourceGroupManager::setLoadingListener(Ogre::ResourceLoadingListener*)
Ogre::ResourceGroupManager::getLoadingListener()
Ogre::ResourceGroupManager::getSingleton()
Ogre::ResourceGroupManager::getSingletonPtr()
Ogre::ResourceGroupManager::ResourceDeclaration::~ResourceDeclaration()
Ogre::ResourceGroupManager::ResourceDeclaration::operator=(Ogre::ResourceGroupManager::ResourceDeclaration const&)
Ogre::ResourceGroupManager::ResourceDeclaration::ResourceDeclaration(Ogre::ResourceGroupManager::ResourceDeclaration const&)
Ogre::ResourceGroupManager::ResourceDeclaration::ResourceDeclaration()
Ogre::ResourceGroupManager::ResourceLocation::~ResourceLocation()
Ogre::ResourceGroupManager::ResourceLocation::operator=(Ogre::ResourceGroupManager::ResourceLocation const&)
Ogre::ResourceGroupManager::ResourceLocation::ResourceLocation(Ogre::ResourceGroupManager::ResourceLocation const&)
Ogre::ResourceGroupManager::ResourceLocation::ResourceLocation()
Ogre::ResourceGroupManager::ResourceGroup::~ResourceGroup()
Ogre::ResourceGroupManager::ResourceGroup::ResourceGroup()
Ogre::ResourceGroupManager::ResourceGroup::addToIndex(std::string const&, Ogre::Archive*)
Ogre::ResourceGroupManager::ResourceGroup::removeFromIndex(std::string const&, Ogre::Archive*)
Ogre::ResourceGroupManager::ResourceGroup::removeFromIndex(Ogre::Archive*)
*/
<|endoftext|>


<commit_before>#ifdef __APPLE__
	#include <Glut/glut.h>
#else
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
#endif

#include "Robot/BipodModel.h"
#include "Robot/PhaserModel.h"
#include "Material/MetalMaterial.h"

BipodModel::BipodModel(void)
{
    teamNumber = new TeamNumberModel();
    material = (Material*)(new MetalMaterial());
}

void BipodModel::render(){

	TextureManager::getInstance()->enableTexture();
	glPushMatrix();
		glTranslatef(.8f, 0.0f, 1.0f);
		glRotatef(180,0,1,0);
		glScalef(.65f, .65f, .65f);
		//first leg
		drawLeg();

		//second leg
		glTranslatef(0.0f, 0.0f, 1.0f);
		drawLeg();
		glTranslatef(0.0f, 0.0f, -1.0f);

		glTranslatef(0.f, 1.3f, 0.f);
		//rectangle
		glPushMatrix();
			glBindTexture(GL_TEXTURE_2D, TextureManager::getInstance()->getTextures("rustymetal.bmp"));
			glBegin(GL_QUADS);
				glNormal3f(0.0f, 0.0f, -1.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 0.0f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(0.0f, 0.2f, 0.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(1.0f, 0.2f, 0.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(1.0f, 0.0f, 0.0f);

				glNormal3f(0.0f, 0.0f, 1.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(1.0f, 0.0f, 1.5f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(1.0f, 0.2f, 1.5f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(0.0f, 0.2f, 1.5f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 1.5f);
			glEnd();

			glBegin(GL_QUAD_STRIP);
				glNormal3f(-1.0f, 0.0f, 0.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 0.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 1.5f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(0.0f, 0.2f, 0.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(0.0f, 0.2f, 1.5f);

				glNormal3f(0.0f, 1.0f, 0.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(1.0f, 0.2f, 0.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(1.0f, 0.2f, 1.5f);

				glNormal3f(1.0f, 0.0f, 0.0f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(1.0f, 0.0f, 0.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(1.0f, 0.0f, 1.5f);

				glNormal3f(0.0f, -1.0f, 0.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 0.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 1.5f);
			glEnd();
		glPopMatrix();
	glPopMatrix();
	glTranslated(0,1,0);
}

void BipodModel::drawLeg(){
	GLUquadricObj *qbipod = gluNewQuadric();
	gluQuadricNormals(qbipod, GLU_SMOOTH);
	TextureManager::getInstance()->enableTexture();
	glPushMatrix();
		glTranslatef(0.25f,0.4f,0.25f);
		glPushMatrix();
			//thigh
			glTranslatef(0.0f,1.0f,0.0f);
			glPushMatrix();
				glBindTexture(GL_TEXTURE_2D, TextureManager::getInstance()->getTextures("steel.bmp"));
				gluQuadricTexture(qbipod,true);

				glRotatef(90, 0.0f, 1.0f, 0.0f);
				glRotatef(45, 1.0f, 0.0f, 0.0f);
				gluCylinder(qbipod, 0.1, 0.1, 0.6, 15, 15);
			glPopMatrix();
			glTranslatef(0.0f,-1.0f,0.0f);

			//leg
			glPushMatrix();
				glBindTexture(GL_TEXTURE_2D, TextureManager::getInstance()->getTextures("steel.bmp"));
				gluQuadricTexture(qbipod,true);

				glRotatef(90, 0.0f, 1.0f, 0.0f);
				glRotatef(-45, 1.0f, 0.0f, 0.0f);
				gluCylinder(qbipod, 0.1, 0.1, 0.6, 15, 15);
			glPopMatrix();

			//knee
			glTranslatef(0.45f, 0.5f, 0.0f);
			glPushMatrix();
				glBindTexture(GL_TEXTURE_2D, TextureManager::getInstance()->getTextures("steel.bmp"));
				gluQuadricTexture(qbipod,true);

				gluSphere(qbipod,0.15,15,15);
			glPopMatrix();
			glTranslatef(-0.45f, -0.5f, 0.0f);
		glPopMatrix();
		glTranslatef(-0.25f,-0.4f,-0.25f);

		//feet
		glPushMatrix();
			glScalef(.5f,.5f,.5f);
			glRotatef(-90, 0.0f,1.0f, 0.0f);
			glRotatef(90, 1.0f,0.0f, 0.0f);
			teamNumber->render();
		glPopMatrix();
		TextureManager::getInstance()->enableTexture();
		glBindTexture(GL_TEXTURE_2D, TextureManager::getInstance()->getTextures("bipodf.bmp"));
		glBegin(GL_QUADS);
			glNormal3f(0.0f, 0.0f, -1.0f);
			glTexCoord2f(0.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.0f);
			glTexCoord2f(0.0f, 1.0f);
			glVertex3f(0.0f, 0.5f, 0.0f);
			glTexCoord2f(0.5f, 1.0f);
			glVertex3f(0.5f, 0.5f, 0.0f);
			glTexCoord2f(1.0f, 0.0f);
			glVertex3f(1.0f, 0.0f, 0.0f);

			glNormal3f(0.0f, 0.0f, 1.0f);
			glTexCoord2f(0.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.5f);
			glTexCoord2f(1.0f, 0.0f);
			glVertex3f(1.0f, 0.0f, 0.5f);
			glTexCoord2f(0.5f, 1.0f);
			glVertex3f(0.5f, 0.5f, 0.5f);
			glTexCoord2f(0.0f, 1.0f);
			glVertex3f(0.0f, 0.5f, 0.5f);
		glEnd();

		glBegin(GL_QUAD_STRIP);
			glNormal3f(-1.0f, 0.0f, 0.0f);
			glTexCoord2f(0.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.0f);
			glTexCoord2f(1.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.5f);
			glTexCoord2f(0.0f, 1.0f);
			glVertex3f(0.0f, 0.5f, 0.0f);
			glTexCoord2f(1.0f, 1.0f);
			glVertex3f(0.0f, 0.5f, 0.5f);

			glNormal3f(0.0f, 1.0f, 0.0f);
			glTexCoord2f(0.0f, 0.0f);
			glVertex3f(0.5f, 0.5f, 0.0f);
			glTexCoord2f(1.0f, 0.0f);
			glVertex3f(0.5f, 0.5f, 0.5f);

			glNormal3f(1.0f, 1.0f, 0.0f);
			glTexCoord2f(0.0f, 1.0f);
			glVertex3f(1.0f, 0.0f, 0.0f);
			glTexCoord2f(1.0f, 1.0f);
			glVertex3f(1.0f, 0.0f, 0.5f);

			glNormal3f(0.0f, -1.0f, 0.0f);
			glTexCoord2f(0.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.0f);
			glTexCoord2f(1.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.5f);
		glEnd();
	glPopMatrix();
	gluDeleteQuadric(qbipod);
}<commit_msg>small update to bipod<commit_after>#ifdef __APPLE__
	#include <Glut/glut.h>
#else
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
#endif

#include "Robot/BipodModel.h"
#include "Robot/PhaserModel.h"
#include "Material/MetalMaterial.h"

BipodModel::BipodModel(void)
{
    teamNumber = new TeamNumberModel();
    material = (Material*)(new MetalMaterial());
}

void BipodModel::render(){

	TextureManager::getInstance()->enableTexture();
	glPushMatrix();
		glTranslatef(.8f, 0.0f, 1.0f);
		glRotatef(180,0,1,0);
		glScalef(.65f, .65f, .65f);
		//first leg
		drawLeg();

		//second leg
		glTranslatef(0.0f, 0.0f, 1.0f);
		drawLeg();
		glTranslatef(0.0f, 0.0f, -1.0f);

		glTranslatef(0.f, 1.3f, 0.f);
		//rectangle
		glPushMatrix();
			glBindTexture(GL_TEXTURE_2D, TextureManager::getInstance()->getTextures("rustymetal.bmp"));
			glBegin(GL_QUADS);
				glNormal3f(0.0f, 0.0f, -1.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 0.0f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(0.0f, 0.2f, 0.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(1.0f, 0.2f, 0.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(1.0f, 0.0f, 0.0f);

				glNormal3f(0.0f, 0.0f, 1.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(1.0f, 0.0f, 1.5f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(1.0f, 0.2f, 1.5f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(0.0f, 0.2f, 1.5f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 1.5f);
			glEnd();

			glBegin(GL_QUAD_STRIP);
				glNormal3f(-1.0f, 0.0f, 0.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 0.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 1.5f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(0.0f, 0.2f, 0.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(0.0f, 0.2f, 1.5f);

				glNormal3f(0.0f, 1.0f, 0.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(1.0f, 0.2f, 0.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(1.0f, 0.2f, 1.5f);

				glNormal3f(1.0f, 0.0f, 0.0f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(1.0f, 0.0f, 0.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(1.0f, 0.0f, 1.5f);

				glNormal3f(0.0f, -1.0f, 0.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 0.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(0.0f, 0.0f, 1.5f);
			glEnd();
		glPopMatrix();
	glPopMatrix();
	glTranslated(0,1,0);
	glDisable(GL_TEXTURE_2D);
}

void BipodModel::drawLeg(){
	GLUquadricObj *qbipod = gluNewQuadric();
	gluQuadricNormals(qbipod, GLU_SMOOTH);
	TextureManager::getInstance()->enableTexture();
	glPushMatrix();
		glTranslatef(0.25f,0.4f,0.25f);
		glPushMatrix();
			//thigh
			glTranslatef(0.0f,1.0f,0.0f);
			glPushMatrix();
				glBindTexture(GL_TEXTURE_2D, TextureManager::getInstance()->getTextures("steel.bmp"));
				gluQuadricTexture(qbipod,true);

				glRotatef(90, 0.0f, 1.0f, 0.0f);
				glRotatef(45, 1.0f, 0.0f, 0.0f);
				gluCylinder(qbipod, 0.1, 0.1, 0.6, 15, 15);
			glPopMatrix();
			glTranslatef(0.0f,-1.0f,0.0f);

			//leg
			glPushMatrix();
				glBindTexture(GL_TEXTURE_2D, TextureManager::getInstance()->getTextures("steel.bmp"));
				gluQuadricTexture(qbipod,true);

				glRotatef(90, 0.0f, 1.0f, 0.0f);
				glRotatef(-45, 1.0f, 0.0f, 0.0f);
				gluCylinder(qbipod, 0.1, 0.1, 0.6, 15, 15);
			glPopMatrix();

			//knee
			glTranslatef(0.45f, 0.5f, 0.0f);
			glPushMatrix();
				glBindTexture(GL_TEXTURE_2D, TextureManager::getInstance()->getTextures("steel.bmp"));
				gluQuadricTexture(qbipod,true);

				gluSphere(qbipod,0.15,15,15);
			glPopMatrix();
			glTranslatef(-0.45f, -0.5f, 0.0f);
		glPopMatrix();
		glTranslatef(-0.25f,-0.4f,-0.25f);

		//feet
		glPushMatrix();
			glScalef(.5f,.5f,.5f);
			glRotatef(-90, 0.0f,1.0f, 0.0f);
			glRotatef(90, 1.0f,0.0f, 0.0f);
			teamNumber->render();
		glPopMatrix();
		TextureManager::getInstance()->enableTexture();
		glBindTexture(GL_TEXTURE_2D, TextureManager::getInstance()->getTextures("bipodf.bmp"));
		glBegin(GL_QUADS);
			glNormal3f(0.0f, 0.0f, -1.0f);
			glTexCoord2f(0.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.0f);
			glTexCoord2f(0.0f, 1.0f);
			glVertex3f(0.0f, 0.5f, 0.0f);
			glTexCoord2f(0.5f, 1.0f);
			glVertex3f(0.5f, 0.5f, 0.0f);
			glTexCoord2f(1.0f, 0.0f);
			glVertex3f(1.0f, 0.0f, 0.0f);

			glNormal3f(0.0f, 0.0f, 1.0f);
			glTexCoord2f(0.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.5f);
			glTexCoord2f(1.0f, 0.0f);
			glVertex3f(1.0f, 0.0f, 0.5f);
			glTexCoord2f(0.5f, 1.0f);
			glVertex3f(0.5f, 0.5f, 0.5f);
			glTexCoord2f(0.0f, 1.0f);
			glVertex3f(0.0f, 0.5f, 0.5f);
		glEnd();

		glBegin(GL_QUAD_STRIP);
			glNormal3f(-1.0f, 0.0f, 0.0f);
			glTexCoord2f(0.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.0f);
			glTexCoord2f(1.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.5f);
			glTexCoord2f(0.0f, 1.0f);
			glVertex3f(0.0f, 0.5f, 0.0f);
			glTexCoord2f(1.0f, 1.0f);
			glVertex3f(0.0f, 0.5f, 0.5f);

			glNormal3f(0.0f, 1.0f, 0.0f);
			glTexCoord2f(0.0f, 0.0f);
			glVertex3f(0.5f, 0.5f, 0.0f);
			glTexCoord2f(1.0f, 0.0f);
			glVertex3f(0.5f, 0.5f, 0.5f);

			glNormal3f(1.0f, 1.0f, 0.0f);
			glTexCoord2f(0.0f, 1.0f);
			glVertex3f(1.0f, 0.0f, 0.0f);
			glTexCoord2f(1.0f, 1.0f);
			glVertex3f(1.0f, 0.0f, 0.5f);

			glNormal3f(0.0f, -1.0f, 0.0f);
			glTexCoord2f(0.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.0f);
			glTexCoord2f(1.0f, 0.0f);
			glVertex3f(0.0f, 0.0f, 0.5f);
		glEnd();
	glPopMatrix();
	gluDeleteQuadric(qbipod);
}<|endoftext|>


<commit_before>#include "common/network/dns_impl.h"

#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>

#include <chrono>
#include <cstdint>
#include <list>
#include <memory>
#include <string>

#include "common/common/assert.h"
#include "common/common/fmt.h"
#include "common/network/address_impl.h"
#include "common/network/utility.h"

#include "ares.h"

namespace Envoy {
namespace Network {

DnsResolverImpl::DnsResolverImpl(
    Event::Dispatcher& dispatcher,
    const std::vector<Network::Address::InstanceConstSharedPtr>& resolvers)
    : dispatcher_(dispatcher),
      timer_(dispatcher.createTimer([this] { onEventCallback(ARES_SOCKET_BAD, 0); })) {
  ares_options options;

  initializeChannel(&options, 0);

  if (!resolvers.empty()) {
    std::vector<std::string> resolver_addrs;
    resolver_addrs.reserve(resolvers.size());
    for (const auto& resolver : resolvers) {
      // This should be an IP address (i.e. not a pipe).
      if (resolver->ip() == nullptr) {
        ares_destroy(channel_);
        throw EnvoyException(
            fmt::format("DNS resolver '{}' is not an IP address", resolver->asString()));
      }
      // Note that the ip()->port() may be zero if the port is not fully specified by the
      // Address::Instance.
      // resolver->asString() is avoided as that format may be modified by custom
      // Address::Instance implementations in ways that make the <port> not a simple
      // integer. See https://github.com/envoyproxy/envoy/pull/3366.
      resolver_addrs.push_back(fmt::format(resolver->ip()->ipv6() ? "[{}]:{}" : "{}:{}",
                                           resolver->ip()->addressAsString(),
                                           resolver->ip()->port()));
    }
    const std::string resolvers_csv = StringUtil::join(resolver_addrs, ",");
    int result = ares_set_servers_ports_csv(channel_, resolvers_csv.c_str());
    RELEASE_ASSERT(result == ARES_SUCCESS, "");
  }
}

DnsResolverImpl::~DnsResolverImpl() {
  timer_->disableTimer();
  ares_destroy(channel_);
}

void DnsResolverImpl::initializeChannel(ares_options* options, int optmask) {
  options->sock_state_cb = [](void* arg, int fd, int read, int write) {
    static_cast<DnsResolverImpl*>(arg)->onAresSocketStateChange(fd, read, write);
  };
  options->sock_state_cb_data = this;
  ares_init_options(&channel_, options, optmask | ARES_OPT_SOCK_STATE_CB);
}

void DnsResolverImpl::PendingResolution::onAresHostCallback(int status, int timeouts,
                                                            hostent* hostent) {
  // We receive ARES_EDESTRUCTION when destructing with pending queries.
  if (status == ARES_EDESTRUCTION) {
    ASSERT(owned_);
    delete this;
    return;
  }
  if (!fallback_if_failed_) {
    completed_ = true;
  }

  std::list<Address::InstanceConstSharedPtr> address_list;
  if (status == ARES_SUCCESS) {
    if (hostent->h_addrtype == AF_INET) {
      for (int i = 0; hostent->h_addr_list[i] != nullptr; ++i) {
        ASSERT(hostent->h_length == sizeof(in_addr));
        sockaddr_in address;
        memset(&address, 0, sizeof(address));
        address.sin_family = AF_INET;
        address.sin_port = 0;
        address.sin_addr = *reinterpret_cast<in_addr*>(hostent->h_addr_list[i]);
        address_list.emplace_back(new Address::Ipv4Instance(&address));
      }
    } else if (hostent->h_addrtype == AF_INET6) {
      for (int i = 0; hostent->h_addr_list[i] != nullptr; ++i) {
        ASSERT(hostent->h_length == sizeof(in6_addr));
        sockaddr_in6 address;
        memset(&address, 0, sizeof(address));
        address.sin6_family = AF_INET6;
        address.sin6_port = 0;
        address.sin6_addr = *reinterpret_cast<in6_addr*>(hostent->h_addr_list[i]);
        address_list.emplace_back(new Address::Ipv6Instance(address));
      }
    }
    if (!address_list.empty()) {
      completed_ = true;
    }
  }

  if (timeouts > 0) {
    ENVOY_LOG(debug, "DNS request timed out {} times", timeouts);
  }

  if (completed_) {
    if (!cancelled_) {
      try {
        callback_(std::move(address_list));
      } catch (const EnvoyException& e) {
        ENVOY_LOG(critical, "EnvoyException in c-ares callback");
        dispatcher_.post([s = std::string(e.what())] { throw EnvoyException(s); });
      } catch (const std::exception& e) {
        ENVOY_LOG(critical, "std::exception in c-ares callback");
        dispatcher_.post([s = std::string(e.what())] { throw EnvoyException(s); });
      } catch (...) {
        ENVOY_LOG(critical, "Unknown exception in c-ares callback");
        dispatcher_.post([] { throw EnvoyException("unknown"); });
      }
    }
    if (owned_) {
      delete this;
      return;
    }
  }

  if (!completed_ && fallback_if_failed_) {
    fallback_if_failed_ = false;
    getHostByName(AF_INET);
    // Note: Nothing can follow this call to getHostByName due to deletion of this
    // object upon synchronous resolution.
    return;
  }
}

void DnsResolverImpl::updateAresTimer() {
  // Update the timeout for events.
  timeval timeout;
  timeval* timeout_result = ares_timeout(channel_, nullptr, &timeout);
  if (timeout_result != nullptr) {
    const auto ms =
        std::chrono::milliseconds(timeout_result->tv_sec * 1000 + timeout_result->tv_usec / 1000);
    ENVOY_LOG(debug, "Setting DNS resolution timer for {} milliseconds", ms.count());
    timer_->enableTimer(ms);
  } else {
    timer_->disableTimer();
  }
}

void DnsResolverImpl::onEventCallback(int fd, uint32_t events) {
  const ares_socket_t read_fd = events & Event::FileReadyType::Read ? fd : ARES_SOCKET_BAD;
  const ares_socket_t write_fd = events & Event::FileReadyType::Write ? fd : ARES_SOCKET_BAD;
  ares_process_fd(channel_, read_fd, write_fd);
  updateAresTimer();
}

void DnsResolverImpl::onAresSocketStateChange(int fd, int read, int write) {
  updateAresTimer();
  auto it = events_.find(fd);
  // Stop tracking events for fd if no more state change events.
  if (read == 0 && write == 0) {
    if (it != events_.end()) {
      events_.erase(it);
    }
    return;
  }

  // If we weren't tracking the fd before, create a new FileEvent.
  if (it == events_.end()) {
    events_[fd] = dispatcher_.createFileEvent(
        fd, [this, fd](uint32_t events) { onEventCallback(fd, events); },
        Event::FileTriggerType::Level, Event::FileReadyType::Read | Event::FileReadyType::Write);
  }
  events_[fd]->setEnabled((read ? Event::FileReadyType::Read : 0) |
                          (write ? Event::FileReadyType::Write : 0));
}

ActiveDnsQuery* DnsResolverImpl::resolve(const std::string& dns_name,
                                         DnsLookupFamily dns_lookup_family, ResolveCb callback) {
  // TODO(hennna): Add DNS caching which will allow testing the edge case of a
  // failed initial call to getHostByName followed by a synchronous IPv4
  // resolution.
  std::unique_ptr<PendingResolution> pending_resolution(
      new PendingResolution(callback, dispatcher_, channel_, dns_name));
  if (dns_lookup_family == DnsLookupFamily::Auto) {
    pending_resolution->fallback_if_failed_ = true;
  }

  if (dns_lookup_family == DnsLookupFamily::V4Only) {
    pending_resolution->getHostByName(AF_INET);
  } else {
    pending_resolution->getHostByName(AF_INET6);
  }

  if (pending_resolution->completed_) {
    // Resolution does not need asynchronous behavior or network events. For
    // example, localhost lookup.
    return nullptr;
  } else {
    // Enable timer to wake us up if the request times out.
    updateAresTimer();

    // The PendingResolution will self-delete when the request completes
    // (including if cancelled or if ~DnsResolverImpl() happens).
    pending_resolution->owned_ = true;
    return pending_resolution.release();
  }
}

void DnsResolverImpl::PendingResolution::getHostByName(int family) {
  ares_gethostbyname(
      channel_, dns_name_.c_str(), family,
      [](void* arg, int status, int timeouts, hostent* hostent) {
        static_cast<PendingResolution*>(arg)->onAresHostCallback(status, timeouts, hostent);
      },
      this);
}

} // namespace Network
} // namespace Envoy
<commit_msg>downgrade dns log level (#7176)<commit_after>#include "common/network/dns_impl.h"

#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>

#include <chrono>
#include <cstdint>
#include <list>
#include <memory>
#include <string>

#include "common/common/assert.h"
#include "common/common/fmt.h"
#include "common/network/address_impl.h"
#include "common/network/utility.h"

#include "ares.h"

namespace Envoy {
namespace Network {

DnsResolverImpl::DnsResolverImpl(
    Event::Dispatcher& dispatcher,
    const std::vector<Network::Address::InstanceConstSharedPtr>& resolvers)
    : dispatcher_(dispatcher),
      timer_(dispatcher.createTimer([this] { onEventCallback(ARES_SOCKET_BAD, 0); })) {
  ares_options options;

  initializeChannel(&options, 0);

  if (!resolvers.empty()) {
    std::vector<std::string> resolver_addrs;
    resolver_addrs.reserve(resolvers.size());
    for (const auto& resolver : resolvers) {
      // This should be an IP address (i.e. not a pipe).
      if (resolver->ip() == nullptr) {
        ares_destroy(channel_);
        throw EnvoyException(
            fmt::format("DNS resolver '{}' is not an IP address", resolver->asString()));
      }
      // Note that the ip()->port() may be zero if the port is not fully specified by the
      // Address::Instance.
      // resolver->asString() is avoided as that format may be modified by custom
      // Address::Instance implementations in ways that make the <port> not a simple
      // integer. See https://github.com/envoyproxy/envoy/pull/3366.
      resolver_addrs.push_back(fmt::format(resolver->ip()->ipv6() ? "[{}]:{}" : "{}:{}",
                                           resolver->ip()->addressAsString(),
                                           resolver->ip()->port()));
    }
    const std::string resolvers_csv = StringUtil::join(resolver_addrs, ",");
    int result = ares_set_servers_ports_csv(channel_, resolvers_csv.c_str());
    RELEASE_ASSERT(result == ARES_SUCCESS, "");
  }
}

DnsResolverImpl::~DnsResolverImpl() {
  timer_->disableTimer();
  ares_destroy(channel_);
}

void DnsResolverImpl::initializeChannel(ares_options* options, int optmask) {
  options->sock_state_cb = [](void* arg, int fd, int read, int write) {
    static_cast<DnsResolverImpl*>(arg)->onAresSocketStateChange(fd, read, write);
  };
  options->sock_state_cb_data = this;
  ares_init_options(&channel_, options, optmask | ARES_OPT_SOCK_STATE_CB);
}

void DnsResolverImpl::PendingResolution::onAresHostCallback(int status, int timeouts,
                                                            hostent* hostent) {
  // We receive ARES_EDESTRUCTION when destructing with pending queries.
  if (status == ARES_EDESTRUCTION) {
    ASSERT(owned_);
    delete this;
    return;
  }
  if (!fallback_if_failed_) {
    completed_ = true;
  }

  std::list<Address::InstanceConstSharedPtr> address_list;
  if (status == ARES_SUCCESS) {
    if (hostent->h_addrtype == AF_INET) {
      for (int i = 0; hostent->h_addr_list[i] != nullptr; ++i) {
        ASSERT(hostent->h_length == sizeof(in_addr));
        sockaddr_in address;
        memset(&address, 0, sizeof(address));
        address.sin_family = AF_INET;
        address.sin_port = 0;
        address.sin_addr = *reinterpret_cast<in_addr*>(hostent->h_addr_list[i]);
        address_list.emplace_back(new Address::Ipv4Instance(&address));
      }
    } else if (hostent->h_addrtype == AF_INET6) {
      for (int i = 0; hostent->h_addr_list[i] != nullptr; ++i) {
        ASSERT(hostent->h_length == sizeof(in6_addr));
        sockaddr_in6 address;
        memset(&address, 0, sizeof(address));
        address.sin6_family = AF_INET6;
        address.sin6_port = 0;
        address.sin6_addr = *reinterpret_cast<in6_addr*>(hostent->h_addr_list[i]);
        address_list.emplace_back(new Address::Ipv6Instance(address));
      }
    }
    if (!address_list.empty()) {
      completed_ = true;
    }
  }

  if (timeouts > 0) {
    ENVOY_LOG(debug, "DNS request timed out {} times", timeouts);
  }

  if (completed_) {
    if (!cancelled_) {
      try {
        callback_(std::move(address_list));
      } catch (const EnvoyException& e) {
        ENVOY_LOG(critical, "EnvoyException in c-ares callback");
        dispatcher_.post([s = std::string(e.what())] { throw EnvoyException(s); });
      } catch (const std::exception& e) {
        ENVOY_LOG(critical, "std::exception in c-ares callback");
        dispatcher_.post([s = std::string(e.what())] { throw EnvoyException(s); });
      } catch (...) {
        ENVOY_LOG(critical, "Unknown exception in c-ares callback");
        dispatcher_.post([] { throw EnvoyException("unknown"); });
      }
    }
    if (owned_) {
      delete this;
      return;
    }
  }

  if (!completed_ && fallback_if_failed_) {
    fallback_if_failed_ = false;
    getHostByName(AF_INET);
    // Note: Nothing can follow this call to getHostByName due to deletion of this
    // object upon synchronous resolution.
    return;
  }
}

void DnsResolverImpl::updateAresTimer() {
  // Update the timeout for events.
  timeval timeout;
  timeval* timeout_result = ares_timeout(channel_, nullptr, &timeout);
  if (timeout_result != nullptr) {
    const auto ms =
        std::chrono::milliseconds(timeout_result->tv_sec * 1000 + timeout_result->tv_usec / 1000);
    ENVOY_LOG(trace, "Setting DNS resolution timer for {} milliseconds", ms.count());
    timer_->enableTimer(ms);
  } else {
    timer_->disableTimer();
  }
}

void DnsResolverImpl::onEventCallback(int fd, uint32_t events) {
  const ares_socket_t read_fd = events & Event::FileReadyType::Read ? fd : ARES_SOCKET_BAD;
  const ares_socket_t write_fd = events & Event::FileReadyType::Write ? fd : ARES_SOCKET_BAD;
  ares_process_fd(channel_, read_fd, write_fd);
  updateAresTimer();
}

void DnsResolverImpl::onAresSocketStateChange(int fd, int read, int write) {
  updateAresTimer();
  auto it = events_.find(fd);
  // Stop tracking events for fd if no more state change events.
  if (read == 0 && write == 0) {
    if (it != events_.end()) {
      events_.erase(it);
    }
    return;
  }

  // If we weren't tracking the fd before, create a new FileEvent.
  if (it == events_.end()) {
    events_[fd] = dispatcher_.createFileEvent(
        fd, [this, fd](uint32_t events) { onEventCallback(fd, events); },
        Event::FileTriggerType::Level, Event::FileReadyType::Read | Event::FileReadyType::Write);
  }
  events_[fd]->setEnabled((read ? Event::FileReadyType::Read : 0) |
                          (write ? Event::FileReadyType::Write : 0));
}

ActiveDnsQuery* DnsResolverImpl::resolve(const std::string& dns_name,
                                         DnsLookupFamily dns_lookup_family, ResolveCb callback) {
  // TODO(hennna): Add DNS caching which will allow testing the edge case of a
  // failed initial call to getHostByName followed by a synchronous IPv4
  // resolution.
  std::unique_ptr<PendingResolution> pending_resolution(
      new PendingResolution(callback, dispatcher_, channel_, dns_name));
  if (dns_lookup_family == DnsLookupFamily::Auto) {
    pending_resolution->fallback_if_failed_ = true;
  }

  if (dns_lookup_family == DnsLookupFamily::V4Only) {
    pending_resolution->getHostByName(AF_INET);
  } else {
    pending_resolution->getHostByName(AF_INET6);
  }

  if (pending_resolution->completed_) {
    // Resolution does not need asynchronous behavior or network events. For
    // example, localhost lookup.
    return nullptr;
  } else {
    // Enable timer to wake us up if the request times out.
    updateAresTimer();

    // The PendingResolution will self-delete when the request completes
    // (including if cancelled or if ~DnsResolverImpl() happens).
    pending_resolution->owned_ = true;
    return pending_resolution.release();
  }
}

void DnsResolverImpl::PendingResolution::getHostByName(int family) {
  ares_gethostbyname(
      channel_, dns_name_.c_str(), family,
      [](void* arg, int status, int timeouts, hostent* hostent) {
        static_cast<PendingResolution*>(arg)->onAresHostCallback(status, timeouts, hostent);
      },
      this);
}

} // namespace Network
} // namespace Envoy
<|endoftext|>