<commit_before>/*
** Copyright 2015 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include "com/centreon/broker/correlation/stream.hh"
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/persistent_cache.hh"
#include "com/centreon/broker/correlation/engine_state.hh"
#include "com/centreon/broker/correlation/node.hh"
#include "com/centreon/broker/correlation/parser.hh"
#include "com/centreon/broker/neb/host_status.hh"
#include "com/centreon/broker/neb/service_status.hh"
#include "com/centreon/broker/neb/log_entry.hh"
#include "com/centreon/broker/notification/acknowledgement.hh"
#include "com/centreon/broker/notification/downtime.hh"
#include "com/centreon/broker/notification/downtime_removed.hh"
#include "com/centreon/broker/multiplexing/publisher.hh"
#include "com/centreon/broker/logging/logging.hh"

extern unsigned int instance_id;

using namespace com::centreon::broker;
using namespace com::centreon::broker::correlation;

/**
 *  Constructor.
 *
 *  @param[in]      correlation_file  Correlation file.
 *  @param[int,out] cache             Persistent cache.
 */
stream::stream(
          QString const& correlation_file,
	  misc::shared_ptr<persistent_cache> cache)
  : _correlation_file(correlation_file),
    _process_out(true),
    _cache(cache) {
  // Create the engine started event.
  multiplexing::publisher pblsh;
  misc::shared_ptr<engine_state> es(new engine_state);
  es->instance_id = instance_id;
  es->started = true;
  pblsh.write(es);

  // Load the correlation.
  _load_correlation();
}

/**
 *  Destructor.
 */
stream::~stream() {
  try {
    multiplexing::publisher pblsh;
    misc::shared_ptr<engine_state> es(new engine_state);
    es->instance_id = instance_id;
    pblsh.write(es);
  } catch (std::exception const& e) {
    logging::error(logging::medium)
      << "correlator: error while trying to publish engine state: "
      << e.what();
  }
}

/**
 *  Set which data to process.
 *
 *  @param[in] in   Process in.
 *  @param[in] out  Process out.
 */
void stream::process(bool in, bool out) {
  bool was_processing(_process_out);
  _process_out = in || !out; // Only for immediate shutdown.
  if (was_processing && !_process_out)
    _save_persistent_cache();
  return ;
}

/**
 *  Read data from the stream.
 *
 *  @param[out] d  Unused.
 */
void stream::read(misc::shared_ptr<io::data>& d) {
  d.clear();
  throw (exceptions::msg()
	 << "correlation: cannot read from a stream. This is likely a "
	 << "software bug that you should report to Centreon Broker "
	 << "developers");
  return ;
}

/**
 *  Update the stream.
 */
void stream::update() {
  _save_persistent_cache();
  _load_correlation();
  return ;
}

/**
 *  Write data to the correlation stream.
 *
 *  @param[in] d  Multiplexed data.
 */
unsigned int stream::write(misc::shared_ptr<io::data> const& d) {
  // Check that data can be processed.
  if (!_process_out)
    throw (io::exceptions::shutdown(true, true)
	   << "correlation stream is shutdown");

  if (d.isNull())
    return (1);

  if (d->type() == neb::host_status::static_type()) {
    neb::host_status const& hs = d.ref_as<neb::host_status>();
    QPair<unsigned int, unsigned int> id(hs.host_id, 0);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_status(
        hs.last_hard_state,
        hs.last_hard_state_change,
        &pblsh);
    }
  }
  else if (d->type() == neb::service_status::static_type()) {
    neb::service_status const& ss = d.ref_as<neb::service_status>();
    QPair<unsigned int, unsigned int> id(ss.host_id, ss.service_id);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_status(
        ss.last_hard_state,
        ss.last_hard_state_change,
        &pblsh);
    }
  }
  else if (d->type() == notification::acknowledgement::static_type()) {
    notification::acknowledgement const& ack
      = d.ref_as<notification::acknowledgement>();
    QPair<unsigned int, unsigned int> id(ack.host_id, ack.service_id);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_ack(ack.entry_time, &pblsh);
    }
  }
  else if (d->type() == notification::downtime::static_type()) {
    notification::downtime const& dwn = d.ref_as<notification::downtime>();
    QPair<unsigned int, unsigned int> id(dwn.host_id, dwn.service_id);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_downtime(dwn, &pblsh);
    }
  }
  else if (d->type() == neb::log_entry::static_type()) {
    neb::log_entry const& entry = d.ref_as<neb::log_entry>();
    QPair<unsigned int, unsigned int> id(entry.host_id, entry.service_id);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_log(entry, &pblsh);
    }
  }
  else if (d->type() == notification::downtime_removed::static_type()) {
    notification::downtime_removed const& dr
      = d.ref_as<notification::downtime_removed>();
    QPair<unsigned int, unsigned int> id(dr.host_id, dr.service_id);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_downtime_removed(dr.downtime_id, &pblsh);
    }
  }
}

/**
 *  Load correlation from the configuration file and the persistent
 *  cache.
 */
void stream::_load_correlation() {
  parser p;
  p.parse(_correlation_file, _nodes);

  // No cache, nothing to do.
  if (_cache.isNull())
    return ;
}

/**
 *  Save content of the correlation memory in the persistent cache.
 */
void stream::_save_persistent_cache() {
  // No cache, nothing to do.
  if (_cache.isNull())
    return ;

}
<commit_msg>Correlation: add the return in the write.<commit_after>/*
** Copyright 2015 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include "com/centreon/broker/correlation/stream.hh"
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/persistent_cache.hh"
#include "com/centreon/broker/correlation/engine_state.hh"
#include "com/centreon/broker/correlation/node.hh"
#include "com/centreon/broker/correlation/parser.hh"
#include "com/centreon/broker/neb/host_status.hh"
#include "com/centreon/broker/neb/service_status.hh"
#include "com/centreon/broker/neb/log_entry.hh"
#include "com/centreon/broker/notification/acknowledgement.hh"
#include "com/centreon/broker/notification/downtime.hh"
#include "com/centreon/broker/notification/downtime_removed.hh"
#include "com/centreon/broker/multiplexing/publisher.hh"
#include "com/centreon/broker/logging/logging.hh"

extern unsigned int instance_id;

using namespace com::centreon::broker;
using namespace com::centreon::broker::correlation;

/**
 *  Constructor.
 *
 *  @param[in]      correlation_file  Correlation file.
 *  @param[int,out] cache             Persistent cache.
 */
stream::stream(
          QString const& correlation_file,
	  misc::shared_ptr<persistent_cache> cache)
  : _correlation_file(correlation_file),
    _process_out(true),
    _cache(cache) {
  // Create the engine started event.
  multiplexing::publisher pblsh;
  misc::shared_ptr<engine_state> es(new engine_state);
  es->instance_id = instance_id;
  es->started = true;
  pblsh.write(es);

  // Load the correlation.
  _load_correlation();
}

/**
 *  Destructor.
 */
stream::~stream() {
  try {
    multiplexing::publisher pblsh;
    misc::shared_ptr<engine_state> es(new engine_state);
    es->instance_id = instance_id;
    pblsh.write(es);
  } catch (std::exception const& e) {
    logging::error(logging::medium)
      << "correlator: error while trying to publish engine state: "
      << e.what();
  }
}

/**
 *  Set which data to process.
 *
 *  @param[in] in   Process in.
 *  @param[in] out  Process out.
 */
void stream::process(bool in, bool out) {
  bool was_processing(_process_out);
  _process_out = in || !out; // Only for immediate shutdown.
  if (was_processing && !_process_out)
    _save_persistent_cache();
  return ;
}

/**
 *  Read data from the stream.
 *
 *  @param[out] d  Unused.
 */
void stream::read(misc::shared_ptr<io::data>& d) {
  d.clear();
  throw (exceptions::msg()
	 << "correlation: cannot read from a stream. This is likely a "
	 << "software bug that you should report to Centreon Broker "
	 << "developers");
  return ;
}

/**
 *  Update the stream.
 */
void stream::update() {
  _save_persistent_cache();
  _load_correlation();
  return ;
}

/**
 *  Write data to the correlation stream.
 *
 *  @param[in] d  Multiplexed data.
 */
unsigned int stream::write(misc::shared_ptr<io::data> const& d) {
  // Check that data can be processed.
  if (!_process_out)
    throw (io::exceptions::shutdown(true, true)
	   << "correlation stream is shutdown");

  if (d.isNull())
    return (1);

  if (d->type() == neb::host_status::static_type()) {
    neb::host_status const& hs = d.ref_as<neb::host_status>();
    QPair<unsigned int, unsigned int> id(hs.host_id, 0);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_status(
        hs.last_hard_state,
        hs.last_hard_state_change,
        &pblsh);
    }
  }
  else if (d->type() == neb::service_status::static_type()) {
    neb::service_status const& ss = d.ref_as<neb::service_status>();
    QPair<unsigned int, unsigned int> id(ss.host_id, ss.service_id);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_status(
        ss.last_hard_state,
        ss.last_hard_state_change,
        &pblsh);
    }
  }
  else if (d->type() == notification::acknowledgement::static_type()) {
    notification::acknowledgement const& ack
      = d.ref_as<notification::acknowledgement>();
    QPair<unsigned int, unsigned int> id(ack.host_id, ack.service_id);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_ack(ack.entry_time, &pblsh);
    }
  }
  else if (d->type() == notification::downtime::static_type()) {
    notification::downtime const& dwn = d.ref_as<notification::downtime>();
    QPair<unsigned int, unsigned int> id(dwn.host_id, dwn.service_id);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_downtime(dwn, &pblsh);
    }
  }
  else if (d->type() == neb::log_entry::static_type()) {
    neb::log_entry const& entry = d.ref_as<neb::log_entry>();
    QPair<unsigned int, unsigned int> id(entry.host_id, entry.service_id);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_log(entry, &pblsh);
    }
  }
  else if (d->type() == notification::downtime_removed::static_type()) {
    notification::downtime_removed const& dr
      = d.ref_as<notification::downtime_removed>();
    QPair<unsigned int, unsigned int> id(dr.host_id, dr.service_id);
    QMap<QPair<unsigned int, unsigned int>, node>::iterator found
      = _nodes.find(id);
    if (found != _nodes.end()) {
      multiplexing::publisher pblsh;
      found->manage_downtime_removed(dr.downtime_id, &pblsh);
    }
  }
  return (1);
}

/**
 *  Load correlation from the configuration file and the persistent
 *  cache.
 */
void stream::_load_correlation() {
  parser p;
  p.parse(_correlation_file, _nodes);

  // No cache, nothing to do.
  if (_cache.isNull())
    return ;
}

/**
 *  Save content of the correlation memory in the persistent cache.
 */
void stream::_save_persistent_cache() {
  // No cache, nothing to do.
  if (_cache.isNull())
    return ;

}
<|endoftext|>


<commit_before>#include "InterruptManager.h"
#include <string.h>

#define CHAIN_INITIAL_SIZE    4

namespace mbed {

typedef void (*pvoidf)(void);

InterruptManager* InterruptManager::_instance = (InterruptManager*)NULL;

InterruptManager* InterruptManager::get() {
    if (NULL == _instance)
        _instance = new InterruptManager();
    return _instance;
}

InterruptManager::InterruptManager() {
    memset(_chains, 0, NVIC_NUM_VECTORS * sizeof(CallChain*));
}

void InterruptManager::destroy() {
    // Not a good idea to call this unless NO interrupt at all
    // is under the control of the handler; otherwise, a system crash
    // is very likely to occur
    if (NULL != _instance) {
        delete _instance;
        _instance = (InterruptManager*)NULL;
    }
}

InterruptManager::~InterruptManager() {
    for(int i = 0; i < NVIC_NUM_VECTORS; i++)
        if (NULL != _chains[i])
            delete _chains[i];
}

bool InterruptManager::must_replace_vector(IRQn_Type irq) {
    int irq_pos = get_irq_index(irq);

    if (NULL == _chains[irq_pos]) {
        _chains[irq_pos] = new CallChain(CHAIN_INITIAL_SIZE);
        _chains[irq_pos]->add((pvoidf)NVIC_GetVector(irq));
        return true;
    }
    return false;
}

pFunctionPointer_t InterruptManager::add_common(void (*function)(void), IRQn_Type irq, bool front) {
    int irq_pos = get_irq_index(irq);
    bool change = must_replace_vector(irq);

    pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(function) : _chains[irq_pos]->add(function);
    if (change)
        NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper);
    return pf;
}

bool InterruptManager::remove_handler(pFunctionPointer_t handler, IRQn_Type irq) {
    int irq_pos = get_irq_index(irq);

    if (NULL == _chains[irq_pos])
        return false;
    if (!_chains[irq_pos]->remove(handler))
        return false;
    // If there's a single function left in the chain, swith the interrupt vector
    // to call that function directly. This way we save both time and space.
    if (_chains[irq_pos]->size() == 1 && NULL != _chains[irq_pos]->get(0)->get_function()) {
        NVIC_SetVector(irq, (uint32_t)_chains[irq_pos]->get(0)->get_function());
        delete _chains[irq_pos];
        _chains[irq_pos] = (CallChain*) NULL;
    }
    return true;
}

void InterruptManager::irq_helper() {
    _chains[__get_IPSR()]->call();
}

int InterruptManager::get_irq_index(IRQn_Type irq) {
    return (int)irq + NVIC_USER_IRQ_OFFSET;
}

void InterruptManager::static_irq_helper() {
    InterruptManager::get()->irq_helper();
}

} // namespace mbed

<commit_msg>[RZ/A1H] first release - change InterruptManager.cpp for CA9<commit_after>#include "cmsis.h"
#if defined(NVIC_NUM_VECTORS)

#include "InterruptManager.h"
#include <string.h>

#define CHAIN_INITIAL_SIZE    4

namespace mbed {

typedef void (*pvoidf)(void);

InterruptManager* InterruptManager::_instance = (InterruptManager*)NULL;

InterruptManager* InterruptManager::get() {
    if (NULL == _instance)
        _instance = new InterruptManager();
    return _instance;
}

InterruptManager::InterruptManager() {
    memset(_chains, 0, NVIC_NUM_VECTORS * sizeof(CallChain*));
}

void InterruptManager::destroy() {
    // Not a good idea to call this unless NO interrupt at all
    // is under the control of the handler; otherwise, a system crash
    // is very likely to occur
    if (NULL != _instance) {
        delete _instance;
        _instance = (InterruptManager*)NULL;
    }
}

InterruptManager::~InterruptManager() {
    for(int i = 0; i < NVIC_NUM_VECTORS; i++)
        if (NULL != _chains[i])
            delete _chains[i];
}

bool InterruptManager::must_replace_vector(IRQn_Type irq) {
    int irq_pos = get_irq_index(irq);

    if (NULL == _chains[irq_pos]) {
        _chains[irq_pos] = new CallChain(CHAIN_INITIAL_SIZE);
        _chains[irq_pos]->add((pvoidf)NVIC_GetVector(irq));
        return true;
    }
    return false;
}

pFunctionPointer_t InterruptManager::add_common(void (*function)(void), IRQn_Type irq, bool front) {
    int irq_pos = get_irq_index(irq);
    bool change = must_replace_vector(irq);

    pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(function) : _chains[irq_pos]->add(function);
    if (change)
        NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper);
    return pf;
}

bool InterruptManager::remove_handler(pFunctionPointer_t handler, IRQn_Type irq) {
    int irq_pos = get_irq_index(irq);

    if (NULL == _chains[irq_pos])
        return false;
    if (!_chains[irq_pos]->remove(handler))
        return false;
    // If there's a single function left in the chain, swith the interrupt vector
    // to call that function directly. This way we save both time and space.
    if (_chains[irq_pos]->size() == 1 && NULL != _chains[irq_pos]->get(0)->get_function()) {
        NVIC_SetVector(irq, (uint32_t)_chains[irq_pos]->get(0)->get_function());
        delete _chains[irq_pos];
        _chains[irq_pos] = (CallChain*) NULL;
    }
    return true;
}

void InterruptManager::irq_helper() {
    _chains[__get_IPSR()]->call();
}

int InterruptManager::get_irq_index(IRQn_Type irq) {
    return (int)irq + NVIC_USER_IRQ_OFFSET;
}

void InterruptManager::static_irq_helper() {
    InterruptManager::get()->irq_helper();
}

} // namespace mbed

#endif
<|endoftext|>


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

#ifdef SW_DLLIMPLEMENTATION
#undef SW_DLLIMPLEMENTATION
#endif

#pragma hdrstop

#ifndef _SV_PRINT_HXX //autogen
#include <vcl/print.hxx>
#endif
#ifndef _SV_PRNSETUP_HXX_ //autogen
#include <svtools/prnsetup.hxx>
#endif

#include "swtypes.hxx"
#include "cmdid.h"
#include "envprt.hxx"
#include "envlop.hxx"
#include "uitool.hxx"

#include "envprt.hrc"

SwEnvPrtPage::SwEnvPrtPage(Window* pParent, const SfxItemSet& rSet) :

    SfxTabPage(pParent, SW_RES(TP_ENV_PRT), rSet),

    aAlignBox    (this, SW_RES(BOX_ALIGN  )),
    aTopButton   (this, SW_RES(BTN_TOP    )),
    aBottomButton(this, SW_RES(BTN_BOTTOM )),
    aRightText   (this, SW_RES(TXT_RIGHT  )),
    aRightField  (this, SW_RES(FLD_RIGHT  )),
    aDownText    (this, SW_RES(TXT_DOWN   )),
    aDownField   (this, SW_RES(FLD_DOWN   )),
    aPrinterInfo (this, SW_RES(TXT_PRINTER)),
    aNoNameFL    (this, SW_RES(FL_NONAME )),
    aPrinterFL   (this, SW_RES(FL_PRINTER )),
    aPrtSetup    (this, SW_RES(BTN_PRTSETUP))

{
    FreeResource();
    SetExchangeSupport();

    // Metriken
    FieldUnit eUnit = ::GetDfltMetric(FALSE);
    SetMetric(aRightField, eUnit);
    SetMetric(aDownField , eUnit);

    // Handler installieren
    aTopButton   .SetClickHdl(LINK(this, SwEnvPrtPage, ClickHdl));
    aBottomButton.SetClickHdl(LINK(this, SwEnvPrtPage, ClickHdl));

    aPrtSetup    .SetClickHdl(LINK(this, SwEnvPrtPage, ButtonHdl));

    // Bitmaps
    aBottomButton.GetClickHdl().Call(&aBottomButton);

    // ToolBox
    Size aSz = aAlignBox.CalcWindowSizePixel();
    aAlignBox.SetSizePixel(aSz);
//    aAlignBox.SetPosPixel(Point(aNoNameFL.GetPosPixel().X() + (aNoNameFL.GetSizePixel().Width() - aSz.Width()) / 2, aAlignBox.GetPosPixel().Y()));
    aAlignBox.SetClickHdl(LINK(this, SwEnvPrtPage, AlignHdl));

}

// --------------------------------------------------------------------------

SwEnvPrtPage::~SwEnvPrtPage()
{
}

// --------------------------------------------------------------------------

IMPL_LINK( SwEnvPrtPage, ClickHdl, Button *, EMPTYARG )
{
    sal_Bool bHC = GetDisplayBackground().GetColor().IsDark();
    if (aBottomButton.IsChecked())
    {
        // Briefumschlaege von unten
        aAlignBox.SetItemImage(ITM_HOR_LEFT, Bitmap(SW_RES(bHC ? BMP_HOR_LEFT_LOWER_H : BMP_HOR_LEFT_LOWER)));
        aAlignBox.SetItemImage(ITM_HOR_CNTR, Bitmap(SW_RES(bHC ? BMP_HOR_CNTR_LOWER_H : BMP_HOR_CNTR_LOWER)));
        aAlignBox.SetItemImage(ITM_HOR_RGHT, Bitmap(SW_RES(bHC ? BMP_HOR_RGHT_LOWER_H : BMP_HOR_RGHT_LOWER)));
        aAlignBox.SetItemImage(ITM_VER_LEFT, Bitmap(SW_RES(bHC ? BMP_VER_LEFT_LOWER_H : BMP_VER_LEFT_LOWER)));
        aAlignBox.SetItemImage(ITM_VER_CNTR, Bitmap(SW_RES(bHC ? BMP_VER_CNTR_LOWER_H : BMP_VER_CNTR_LOWER)));
        aAlignBox.SetItemImage(ITM_VER_RGHT, Bitmap(SW_RES(bHC ? BMP_VER_RGHT_LOWER_H : BMP_VER_RGHT_LOWER)));
    }
    else
    {
        // Briefumschlaege von oben
        aAlignBox.SetItemImage(ITM_HOR_LEFT, Bitmap(SW_RES(bHC ? BMP_HOR_LEFT_UPPER_H : BMP_HOR_LEFT_UPPER)));
        aAlignBox.SetItemImage(ITM_HOR_CNTR, Bitmap(SW_RES(bHC ? BMP_HOR_CNTR_UPPER_H : BMP_HOR_CNTR_UPPER)));
        aAlignBox.SetItemImage(ITM_HOR_RGHT, Bitmap(SW_RES(bHC ? BMP_HOR_RGHT_UPPER_H : BMP_HOR_RGHT_UPPER)));
        aAlignBox.SetItemImage(ITM_VER_LEFT, Bitmap(SW_RES(bHC ? BMP_VER_LEFT_UPPER_H : BMP_VER_LEFT_UPPER)));
        aAlignBox.SetItemImage(ITM_VER_CNTR, Bitmap(SW_RES(bHC ? BMP_VER_CNTR_UPPER_H : BMP_VER_CNTR_UPPER)));
        aAlignBox.SetItemImage(ITM_VER_RGHT, Bitmap(SW_RES(bHC ? BMP_VER_RGHT_UPPER_H : BMP_VER_RGHT_UPPER)));
    }
    return 0;
}

// --------------------------------------------------------------------------

IMPL_LINK( SwEnvPrtPage, ButtonHdl, Button *, pBtn )
{
    if (pBtn == &aPrtSetup)
    {
        // Druck-Setup aufrufen
        if (pPrt)
        {
            PrinterSetupDialog* pDlg = new PrinterSetupDialog(this );
            pDlg->SetPrinter(pPrt);
            pDlg->Execute();
            delete pDlg;
            GrabFocus();
            aPrinterInfo.SetText(pPrt->GetName());
        }
    }
    return 0;
}

// --------------------------------------------------------------------------

IMPL_LINK( SwEnvPrtPage, AlignHdl, ToolBox *, EMPTYARG )
{
    if (aAlignBox.GetCurItemId())
    {
        for (USHORT i = ITM_HOR_LEFT; i <= ITM_VER_RGHT; i++)
            aAlignBox.CheckItem(i, FALSE);
        aAlignBox.CheckItem(aAlignBox.GetCurItemId(), TRUE);
    }
    else
    {
        // GetCurItemId() == 0 ist moeglich!
        const SwEnvItem& rItem = (const SwEnvItem&) GetItemSet().Get(FN_ENVELOP);
        aAlignBox.CheckItem((USHORT) rItem.eAlign + ITM_HOR_LEFT, TRUE);
    }
    return 0;
}

// --------------------------------------------------------------------------

SfxTabPage* SwEnvPrtPage::Create(Window* pParent, const SfxItemSet& rSet)
{
    return new SwEnvPrtPage(pParent, rSet);
}

// --------------------------------------------------------------------------

void SwEnvPrtPage::ActivatePage(const SfxItemSet& rSet)
{
    if (pPrt)
        aPrinterInfo.SetText(pPrt->GetName());
}

// --------------------------------------------------------------------------

int SwEnvPrtPage::DeactivatePage(SfxItemSet* pSet)
{
    if( pSet )
        FillItemSet(*pSet);
    return SfxTabPage::LEAVE_PAGE;
}

// --------------------------------------------------------------------------

void SwEnvPrtPage::FillItem(SwEnvItem& rItem)
{
    USHORT nID = 0;
    for (USHORT i = ITM_HOR_LEFT; i <= ITM_VER_RGHT && !nID; i++)
        if (aAlignBox.IsItemChecked(i))
            nID = i;

    rItem.eAlign          = (SwEnvAlign) (nID - ITM_HOR_LEFT);
    rItem.bPrintFromAbove = aTopButton.IsChecked();
    rItem.lShiftRight     = GetFldVal(aRightField);
    rItem.lShiftDown      = GetFldVal(aDownField );
}

// --------------------------------------------------------------------------

BOOL SwEnvPrtPage::FillItemSet(SfxItemSet& rSet)
{
    FillItem(GetParent()->aEnvItem);
    rSet.Put(GetParent()->aEnvItem);
    return TRUE;
}

// ----------------------------------------------------------------------------

void SwEnvPrtPage::Reset(const SfxItemSet& rSet)
{
//    SfxItemSet aSet(rSet);
//    aSet.Put(GetParent()->aEnvItem);

    // Item auslesen
    const SwEnvItem& rItem = (const SwEnvItem&) rSet.Get(FN_ENVELOP);
    aAlignBox.CheckItem((USHORT) rItem.eAlign + ITM_HOR_LEFT);

    if (rItem.bPrintFromAbove)
        aTopButton   .Check();
    else
        aBottomButton.Check();

    SetFldVal(aRightField, rItem.lShiftRight);
    SetFldVal(aDownField , rItem.lShiftDown );

    ActivatePage(rSet);
    ClickHdl(&aTopButton);
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.9.476); FILE MERGED 2006/09/01 17:53:04 kaib 1.9.476.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: envprt.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 22:54:29 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#ifdef SW_DLLIMPLEMENTATION
#undef SW_DLLIMPLEMENTATION
#endif

#ifndef _SV_PRINT_HXX //autogen
#include <vcl/print.hxx>
#endif
#ifndef _SV_PRNSETUP_HXX_ //autogen
#include <svtools/prnsetup.hxx>
#endif

#include "swtypes.hxx"
#include "cmdid.h"
#include "envprt.hxx"
#include "envlop.hxx"
#include "uitool.hxx"

#include "envprt.hrc"

SwEnvPrtPage::SwEnvPrtPage(Window* pParent, const SfxItemSet& rSet) :

    SfxTabPage(pParent, SW_RES(TP_ENV_PRT), rSet),

    aAlignBox    (this, SW_RES(BOX_ALIGN  )),
    aTopButton   (this, SW_RES(BTN_TOP    )),
    aBottomButton(this, SW_RES(BTN_BOTTOM )),
    aRightText   (this, SW_RES(TXT_RIGHT  )),
    aRightField  (this, SW_RES(FLD_RIGHT  )),
    aDownText    (this, SW_RES(TXT_DOWN   )),
    aDownField   (this, SW_RES(FLD_DOWN   )),
    aPrinterInfo (this, SW_RES(TXT_PRINTER)),
    aNoNameFL    (this, SW_RES(FL_NONAME )),
    aPrinterFL   (this, SW_RES(FL_PRINTER )),
    aPrtSetup    (this, SW_RES(BTN_PRTSETUP))

{
    FreeResource();
    SetExchangeSupport();

    // Metriken
    FieldUnit eUnit = ::GetDfltMetric(FALSE);
    SetMetric(aRightField, eUnit);
    SetMetric(aDownField , eUnit);

    // Handler installieren
    aTopButton   .SetClickHdl(LINK(this, SwEnvPrtPage, ClickHdl));
    aBottomButton.SetClickHdl(LINK(this, SwEnvPrtPage, ClickHdl));

    aPrtSetup    .SetClickHdl(LINK(this, SwEnvPrtPage, ButtonHdl));

    // Bitmaps
    aBottomButton.GetClickHdl().Call(&aBottomButton);

    // ToolBox
    Size aSz = aAlignBox.CalcWindowSizePixel();
    aAlignBox.SetSizePixel(aSz);
//    aAlignBox.SetPosPixel(Point(aNoNameFL.GetPosPixel().X() + (aNoNameFL.GetSizePixel().Width() - aSz.Width()) / 2, aAlignBox.GetPosPixel().Y()));
    aAlignBox.SetClickHdl(LINK(this, SwEnvPrtPage, AlignHdl));

}

// --------------------------------------------------------------------------

SwEnvPrtPage::~SwEnvPrtPage()
{
}

// --------------------------------------------------------------------------

IMPL_LINK( SwEnvPrtPage, ClickHdl, Button *, EMPTYARG )
{
    sal_Bool bHC = GetDisplayBackground().GetColor().IsDark();
    if (aBottomButton.IsChecked())
    {
        // Briefumschlaege von unten
        aAlignBox.SetItemImage(ITM_HOR_LEFT, Bitmap(SW_RES(bHC ? BMP_HOR_LEFT_LOWER_H : BMP_HOR_LEFT_LOWER)));
        aAlignBox.SetItemImage(ITM_HOR_CNTR, Bitmap(SW_RES(bHC ? BMP_HOR_CNTR_LOWER_H : BMP_HOR_CNTR_LOWER)));
        aAlignBox.SetItemImage(ITM_HOR_RGHT, Bitmap(SW_RES(bHC ? BMP_HOR_RGHT_LOWER_H : BMP_HOR_RGHT_LOWER)));
        aAlignBox.SetItemImage(ITM_VER_LEFT, Bitmap(SW_RES(bHC ? BMP_VER_LEFT_LOWER_H : BMP_VER_LEFT_LOWER)));
        aAlignBox.SetItemImage(ITM_VER_CNTR, Bitmap(SW_RES(bHC ? BMP_VER_CNTR_LOWER_H : BMP_VER_CNTR_LOWER)));
        aAlignBox.SetItemImage(ITM_VER_RGHT, Bitmap(SW_RES(bHC ? BMP_VER_RGHT_LOWER_H : BMP_VER_RGHT_LOWER)));
    }
    else
    {
        // Briefumschlaege von oben
        aAlignBox.SetItemImage(ITM_HOR_LEFT, Bitmap(SW_RES(bHC ? BMP_HOR_LEFT_UPPER_H : BMP_HOR_LEFT_UPPER)));
        aAlignBox.SetItemImage(ITM_HOR_CNTR, Bitmap(SW_RES(bHC ? BMP_HOR_CNTR_UPPER_H : BMP_HOR_CNTR_UPPER)));
        aAlignBox.SetItemImage(ITM_HOR_RGHT, Bitmap(SW_RES(bHC ? BMP_HOR_RGHT_UPPER_H : BMP_HOR_RGHT_UPPER)));
        aAlignBox.SetItemImage(ITM_VER_LEFT, Bitmap(SW_RES(bHC ? BMP_VER_LEFT_UPPER_H : BMP_VER_LEFT_UPPER)));
        aAlignBox.SetItemImage(ITM_VER_CNTR, Bitmap(SW_RES(bHC ? BMP_VER_CNTR_UPPER_H : BMP_VER_CNTR_UPPER)));
        aAlignBox.SetItemImage(ITM_VER_RGHT, Bitmap(SW_RES(bHC ? BMP_VER_RGHT_UPPER_H : BMP_VER_RGHT_UPPER)));
    }
    return 0;
}

// --------------------------------------------------------------------------

IMPL_LINK( SwEnvPrtPage, ButtonHdl, Button *, pBtn )
{
    if (pBtn == &aPrtSetup)
    {
        // Druck-Setup aufrufen
        if (pPrt)
        {
            PrinterSetupDialog* pDlg = new PrinterSetupDialog(this );
            pDlg->SetPrinter(pPrt);
            pDlg->Execute();
            delete pDlg;
            GrabFocus();
            aPrinterInfo.SetText(pPrt->GetName());
        }
    }
    return 0;
}

// --------------------------------------------------------------------------

IMPL_LINK( SwEnvPrtPage, AlignHdl, ToolBox *, EMPTYARG )
{
    if (aAlignBox.GetCurItemId())
    {
        for (USHORT i = ITM_HOR_LEFT; i <= ITM_VER_RGHT; i++)
            aAlignBox.CheckItem(i, FALSE);
        aAlignBox.CheckItem(aAlignBox.GetCurItemId(), TRUE);
    }
    else
    {
        // GetCurItemId() == 0 ist moeglich!
        const SwEnvItem& rItem = (const SwEnvItem&) GetItemSet().Get(FN_ENVELOP);
        aAlignBox.CheckItem((USHORT) rItem.eAlign + ITM_HOR_LEFT, TRUE);
    }
    return 0;
}

// --------------------------------------------------------------------------

SfxTabPage* SwEnvPrtPage::Create(Window* pParent, const SfxItemSet& rSet)
{
    return new SwEnvPrtPage(pParent, rSet);
}

// --------------------------------------------------------------------------

void SwEnvPrtPage::ActivatePage(const SfxItemSet& rSet)
{
    if (pPrt)
        aPrinterInfo.SetText(pPrt->GetName());
}

// --------------------------------------------------------------------------

int SwEnvPrtPage::DeactivatePage(SfxItemSet* pSet)
{
    if( pSet )
        FillItemSet(*pSet);
    return SfxTabPage::LEAVE_PAGE;
}

// --------------------------------------------------------------------------

void SwEnvPrtPage::FillItem(SwEnvItem& rItem)
{
    USHORT nID = 0;
    for (USHORT i = ITM_HOR_LEFT; i <= ITM_VER_RGHT && !nID; i++)
        if (aAlignBox.IsItemChecked(i))
            nID = i;

    rItem.eAlign          = (SwEnvAlign) (nID - ITM_HOR_LEFT);
    rItem.bPrintFromAbove = aTopButton.IsChecked();
    rItem.lShiftRight     = GetFldVal(aRightField);
    rItem.lShiftDown      = GetFldVal(aDownField );
}

// --------------------------------------------------------------------------

BOOL SwEnvPrtPage::FillItemSet(SfxItemSet& rSet)
{
    FillItem(GetParent()->aEnvItem);
    rSet.Put(GetParent()->aEnvItem);
    return TRUE;
}

// ----------------------------------------------------------------------------

void SwEnvPrtPage::Reset(const SfxItemSet& rSet)
{
//    SfxItemSet aSet(rSet);
//    aSet.Put(GetParent()->aEnvItem);

    // Item auslesen
    const SwEnvItem& rItem = (const SwEnvItem&) rSet.Get(FN_ENVELOP);
    aAlignBox.CheckItem((USHORT) rItem.eAlign + ITM_HOR_LEFT);

    if (rItem.bPrintFromAbove)
        aTopButton   .Check();
    else
        aBottomButton.Check();

    SetFldVal(aRightField, rItem.lShiftRight);
    SetFldVal(aDownField , rItem.lShiftDown );

    ActivatePage(rSet);
    ClickHdl(&aTopButton);
}

<|endoftext|>


<commit_before>#include "I2CBus.h"
#include "exceptions.h"
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <stdio.h>
#include <unistd.h>

// TODO: throw some nicer type of exception that results in a nice error message

I2CBus::I2CBus(const char * deviceName)
{
    fd = open(deviceName, O_RDWR);
    if (fd == -1)
    {
        throw posix_error();
    }
}

I2CBus::~I2CBus()
{
    close(fd);
}

void I2CBus::addressSet(uint8_t address)
{
    int result = ioctl(fd, I2C_SLAVE, address);
    if (result == -1)
    {
        throw errno;
    }
}

void I2CBus::writeByte(uint8_t command, uint8_t data)
{
    int result = i2c_smbus_write_byte_data(fd, command, data);
    if (result == -1)
    {
        throw errno;
    }
}

uint8_t I2CBus::readByte(uint8_t command)
{
    int result = i2c_smbus_read_byte_data(fd, command);
    if (result == -1)
    {
        throw errno;
    }
    return result;
}

void I2CBus::readBlock(uint8_t command, uint8_t size, uint8_t * data)
{
    int result = i2c_smbus_read_i2c_block_data(fd, command, size, data);
    if (result != size)
    {
        throw errno;
    }
}
<commit_msg>Got rid of all 'throw errno's in I2CBus.cpp.<commit_after>#include "I2CBus.h"
#include "exceptions.h"
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <stdio.h>
#include <unistd.h>

I2CBus::I2CBus(const char * deviceName)
{
    fd = open(deviceName, O_RDWR);
    if (fd == -1)
    {
        throw posix_error();
    }
}

I2CBus::~I2CBus()
{
    close(fd);
}

void I2CBus::addressSet(uint8_t address)
{
    int result = ioctl(fd, I2C_SLAVE, address);
    if (result == -1)
    {
        throw posix_error();
    }
}

void I2CBus::writeByte(uint8_t command, uint8_t data)
{
    int result = i2c_smbus_write_byte_data(fd, command, data);
    if (result == -1)
    {
        throw posix_error();
    }
}

uint8_t I2CBus::readByte(uint8_t command)
{
    int result = i2c_smbus_read_byte_data(fd, command);
    if (result == -1)
    {
        throw posix_error();
    }
    return result;
}

void I2CBus::readBlock(uint8_t command, uint8_t size, uint8_t * data)
{
    int result = i2c_smbus_read_i2c_block_data(fd, command, size, data);
    if (result != size)
    {
        throw posix_error();
    }
}
<|endoftext|>


<commit_before>static const size_t DEFAULT_CAPACITY = 10;
static const unsigned int DEFAULT_ADD_REALLOCATION_MULTIPLIER = 2;
static const unsigned int DEFAULT_REMOVE_REALLOCATION_THRESHOLD = 4;
static const unsigned int DEFAULT_REMOVE_REALLOCATION_DIVISOR = 2;

template <typename T>
ArrayList<T>::ArrayList() :
	initialCapacity(DEFAULT_CAPACITY),
	addReallocationMultiplier(DEFAULT_ADD_REALLOCATION_MULTIPLIER),
	removeReallocationThreshold(DEFAULT_REMOVE_REALLOCATION_THRESHOLD),
	removeReallocationDivisor(DEFAULT_REMOVE_REALLOCATION_DIVISOR),
	values(new T[DEFAULT_CAPACITY]),
	size(0),
	capacity(DEFAULT_CAPACITY)
{}

template <typename T>
ArrayList<T>::ArrayList(
	const size_t pCapacity,
	const unsigned int pAddReallocationMultiplier,
	const unsigned int pRemoveReallocationThreshold,
	const unsigned int pRemoveReallocationDivisor
	) :
	initialCapacity(pCapacity),
	addReallocationMultiplier(pAddReallocationMultiplier),
	/* Safety Dance:
 	 * Ensure that the remove reallocation threshold is NEVER lower
 	 * than the rempove reallocation threshold.
 	 * Set the threshold to double the divisor if this happens.
 	 */
	removeReallocationThreshold(
		pRemoveReallocationThreshold < pRemoveReallocationDivisor
			? pRemoveReallocationDivisor * 2
			: pRemoveReallocationThreshold
	),
	removeReallocationDivisor(pRemoveReallocationDivisor),
	values(new T[pCapacity]),
	size(0),
	capacity(pCapacity)
{}

template <typename T>
ArrayList<T>::ArrayList(const ArrayList<T>& pOther) :
	initialCapacity(pOther.capacity),
	addReallocationMultiplier(pOther.addReallocationMultiplier),
	removeReallocationThreshold(pOther.removeReallocationThreshold),
	removeReallocationDivisor(pOther.removeReallocationDivisor),
	values(
		allocateArray(
			pOther.values,
			pOther.size,
			pOther.capacity
		)
	),
	size(pOther.size),
	capacity(pOther.capacity)
{}

/* FunTip: Valgrind yelled at me when I tried to use the value of
 *         initialCapacity to initialize values and capacity.
 *
 *         It reported that capacity was uninitalized during the following
 *         add() invocations which leads me to think that initialCapcity
 *         was uninitalized when I used it to intialize capacity.
 *
 *         From what I can tell online, since initialCapacity is earlier
 *         than values and capacity in both the class declaration and
 *         initializer list, this SHOULD be valid.
 *
 *         Manually doing the declarations appears to of cleared up the error
 *         even though it is less 'maintainable'.
 */
template <typename T>
ArrayList<T>::ArrayList(const IList<T>& pOther) :
	initialCapacity(pOther.getSize() * addReallocationMultiplier),
	addReallocationMultiplier(DEFAULT_ADD_REALLOCATION_MULTIPLIER),
	removeReallocationThreshold(DEFAULT_REMOVE_REALLOCATION_THRESHOLD),
	removeReallocationDivisor(DEFAULT_REMOVE_REALLOCATION_DIVISOR),
	values(new T[pOther.getSize() * addReallocationMultiplier]),
	size(0),
	capacity(pOther.getSize() * addReallocationMultiplier)
{
	for (size_t i = 0; i < pOther.getSize(); ++i)
	{
		add(pOther[i]);
	}
}

template <typename T>
ArrayList<T>::~ArrayList()
{
	delete[] values;
}

template <typename T>
ArrayList<T>& ArrayList<T>::operator=(const ArrayList<T>& pOther)
{
	if (this != &pOther)
	{
		values = allocateArray(
			pOther.values,
			pOther.capacity,
			pOther.size
		);
		size = pOther.size;
		capacity = pOther.capacity;
	}

	return *this;
}

template <typename T>
size_t ArrayList<T>::getSize() const
{
	return size;
}

template <typename T>
size_t ArrayList<T>::getCapacity() const
{
	return capacity;
}

template <typename T>
void ArrayList<T>::add(const T& pValue)
{
	// Expand the array if we pass a specified threshold
	if (capacity == size)
	{
		size_t newCapacity = capacity * addReallocationMultiplier;
		// Gotta handle 0...
		if (newCapacity == 0)
		{
			newCapacity++;
		}
		T* newValues = allocateArray(values, size, newCapacity);
		delete[] values;
		values = newValues;
		capacity = newCapacity;
	}

	memcpy(values + size, &pValue, sizeof(T));
	++size;
}

template <typename T>
IIterator<T>* ArrayList<T>::iterator()
{
	return new Iterator(*this);
}

template <typename T>
void ArrayList<T>::remove(const size_t pIndex)
{
	if (pIndex >= size)
	{
		// TODO: Deal with sprintf later...pain in the...
		string msg = "Exception during ArrayList remove";
		throw IndexOutOfBoundsError(msg);
	}

	--size;
	for (size_t i = pIndex; i < size; ++i)
	{
		values[i] = values[i + 1];
	}

	// Shrink the array if we are only using a small portion of it.
	// To prevent non-stop resizing, the array will not be shrunk
	// past its initial capacity.
	// NERD ALERT: This floating point arithmetic could slow things down
	//             but the potential memory savings is better IMO until
	//             proven otherwise.
	size_t newCapacity = capacity / removeReallocationDivisor;
	if (newCapacity >= initialCapacity && (size * removeReallocationThreshold) < capacity)
	{
		T* newValues = allocateArray(values, size, newCapacity);
		delete[] values;
		values = newValues;
		capacity = newCapacity;
	}
}

template <typename T>
T& ArrayList<T>::get(size_t pIndex) const
{
	if (pIndex >= size)
	{
		// TODO: Deal with sprintf later...pain in the...
		string msg = "Exception during ArrayList get";
		throw IndexOutOfBoundsError(msg);
	}

	return values[pIndex];
}

template <typename T>
T* ArrayList<T>::allocateArray(
	const T* pOrigValues,
	const size_t pOrigValuesSize,
	const size_t pNewCapacity) const
{
	if (pOrigValuesSize > pNewCapacity) {
		// TODO: Throw reallocation error or something
	}

	T* retVal = new T[pNewCapacity];
	size_t origValuesBytes = sizeof(T) * pOrigValuesSize;
	memcpy(retVal, pOrigValues, origValuesBytes);

	return retVal;
}

template <typename T>
ArrayList<T>::Iterator::Iterator(const ArrayList<T>& pImpl) :
	nextIndex(0),
	impl(pImpl)
{}

template <typename T>
bool ArrayList<T>::Iterator::hasNext()
{
	bool retVal = false;

	if (nextIndex < impl.getSize())
	{
		retVal = true;
	}

	return retVal;
}

template <typename T>
T& ArrayList<T>::Iterator::peekNext()
{
	if (!hasNext())
	{
		string msg = "No more elements in ArrayList::Iterator::peekNext()";
		throw new NoMoreElementsError(msg);
	}

	return impl.get(nextIndex);
}

template <typename T>
T& ArrayList<T>::Iterator::next()
{
	if (!hasNext())
	{
		string msg = "No more elements in ArrayList::Iterator::next()";
		throw new NoMoreElementsError(msg);
	}

	return impl.get(nextIndex++);
}
<commit_msg>Woa now...how did this make it through for so long? Redid my development VM and compiled the latest version of clang...I guess they added some more "hey dumbass" checks. For those who don't see it, I was using a member variable before it was set.<commit_after>static const size_t DEFAULT_CAPACITY = 10;
static const unsigned int DEFAULT_ADD_REALLOCATION_MULTIPLIER = 2;
static const unsigned int DEFAULT_REMOVE_REALLOCATION_THRESHOLD = 4;
static const unsigned int DEFAULT_REMOVE_REALLOCATION_DIVISOR = 2;

template <typename T>
ArrayList<T>::ArrayList() :
	initialCapacity(DEFAULT_CAPACITY),
	addReallocationMultiplier(DEFAULT_ADD_REALLOCATION_MULTIPLIER),
	removeReallocationThreshold(DEFAULT_REMOVE_REALLOCATION_THRESHOLD),
	removeReallocationDivisor(DEFAULT_REMOVE_REALLOCATION_DIVISOR),
	values(new T[DEFAULT_CAPACITY]),
	size(0),
	capacity(DEFAULT_CAPACITY)
{}

template <typename T>
ArrayList<T>::ArrayList(
	const size_t pCapacity,
	const unsigned int pAddReallocationMultiplier,
	const unsigned int pRemoveReallocationThreshold,
	const unsigned int pRemoveReallocationDivisor
	) :
	initialCapacity(pCapacity),
	addReallocationMultiplier(pAddReallocationMultiplier),
	/* Safety Dance:
 	 * Ensure that the remove reallocation threshold is NEVER lower
 	 * than the rempove reallocation threshold.
 	 * Set the threshold to double the divisor if this happens.
 	 */
	removeReallocationThreshold(
		pRemoveReallocationThreshold < pRemoveReallocationDivisor
			? pRemoveReallocationDivisor * 2
			: pRemoveReallocationThreshold
	),
	removeReallocationDivisor(pRemoveReallocationDivisor),
	values(new T[pCapacity]),
	size(0),
	capacity(pCapacity)
{}

template <typename T>
ArrayList<T>::ArrayList(const ArrayList<T>& pOther) :
	initialCapacity(pOther.capacity),
	addReallocationMultiplier(pOther.addReallocationMultiplier),
	removeReallocationThreshold(pOther.removeReallocationThreshold),
	removeReallocationDivisor(pOther.removeReallocationDivisor),
	values(
		allocateArray(
			pOther.values,
			pOther.size,
			pOther.capacity
		)
	),
	size(pOther.size),
	capacity(pOther.capacity)
{}

/* FunTip: Valgrind yelled at me when I tried to use the value of
 *         initialCapacity to initialize values and capacity.
 *
 *         It reported that capacity was uninitalized during the following
 *         add() invocations which leads me to think that initialCapcity
 *         was uninitalized when I used it to intialize capacity.
 *
 *         From what I can tell online, since initialCapacity is earlier
 *         than values and capacity in both the class declaration and
 *         initializer list, this SHOULD be valid.
 *
 *         Manually doing the declarations appears to of cleared up the error
 *         even though it is less 'maintainable'.
 */
template <typename T>
ArrayList<T>::ArrayList(const IList<T>& pOther) :
	initialCapacity(pOther.getSize() * DEFAULT_ADD_REALLOCATION_MULTIPLIER),
	addReallocationMultiplier(DEFAULT_ADD_REALLOCATION_MULTIPLIER),
	removeReallocationThreshold(DEFAULT_REMOVE_REALLOCATION_THRESHOLD),
	removeReallocationDivisor(DEFAULT_REMOVE_REALLOCATION_DIVISOR),
	values(new T[pOther.getSize() * addReallocationMultiplier]),
	size(0),
	capacity(pOther.getSize() * addReallocationMultiplier)
{
	for (size_t i = 0; i < pOther.getSize(); ++i)
	{
		add(pOther[i]);
	}
}

template <typename T>
ArrayList<T>::~ArrayList()
{
	delete[] values;
}

template <typename T>
ArrayList<T>& ArrayList<T>::operator=(const ArrayList<T>& pOther)
{
	if (this != &pOther)
	{
		values = allocateArray(
			pOther.values,
			pOther.capacity,
			pOther.size
		);
		size = pOther.size;
		capacity = pOther.capacity;
	}

	return *this;
}

template <typename T>
size_t ArrayList<T>::getSize() const
{
	return size;
}

template <typename T>
size_t ArrayList<T>::getCapacity() const
{
	return capacity;
}

template <typename T>
void ArrayList<T>::add(const T& pValue)
{
	// Expand the array if we pass a specified threshold
	if (capacity == size)
	{
		size_t newCapacity = capacity * addReallocationMultiplier;
		// Gotta handle 0...
		if (newCapacity == 0)
		{
			newCapacity++;
		}
		T* newValues = allocateArray(values, size, newCapacity);
		delete[] values;
		values = newValues;
		capacity = newCapacity;
	}

	memcpy(values + size, &pValue, sizeof(T));
	++size;
}

template <typename T>
IIterator<T>* ArrayList<T>::iterator()
{
	return new Iterator(*this);
}

template <typename T>
void ArrayList<T>::remove(const size_t pIndex)
{
	if (pIndex >= size)
	{
		// TODO: Deal with sprintf later...pain in the...
		string msg = "Exception during ArrayList remove";
		throw IndexOutOfBoundsError(msg);
	}

	--size;
	for (size_t i = pIndex; i < size; ++i)
	{
		values[i] = values[i + 1];
	}

	// Shrink the array if we are only using a small portion of it.
	// To prevent non-stop resizing, the array will not be shrunk
	// past its initial capacity.
	// NERD ALERT: This floating point arithmetic could slow things down
	//             but the potential memory savings is better IMO until
	//             proven otherwise.
	size_t newCapacity = capacity / removeReallocationDivisor;
	if (newCapacity >= initialCapacity && (size * removeReallocationThreshold) < capacity)
	{
		T* newValues = allocateArray(values, size, newCapacity);
		delete[] values;
		values = newValues;
		capacity = newCapacity;
	}
}

template <typename T>
T& ArrayList<T>::get(size_t pIndex) const
{
	if (pIndex >= size)
	{
		// TODO: Deal with sprintf later...pain in the...
		string msg = "Exception during ArrayList get";
		throw IndexOutOfBoundsError(msg);
	}

	return values[pIndex];
}

template <typename T>
T* ArrayList<T>::allocateArray(
	const T* pOrigValues,
	const size_t pOrigValuesSize,
	const size_t pNewCapacity) const
{
	if (pOrigValuesSize > pNewCapacity) {
		// TODO: Throw reallocation error or something
	}

	T* retVal = new T[pNewCapacity];
	size_t origValuesBytes = sizeof(T) * pOrigValuesSize;
	memcpy(retVal, pOrigValues, origValuesBytes);

	return retVal;
}

template <typename T>
ArrayList<T>::Iterator::Iterator(const ArrayList<T>& pImpl) :
	nextIndex(0),
	impl(pImpl)
{}

template <typename T>
bool ArrayList<T>::Iterator::hasNext()
{
	bool retVal = false;

	if (nextIndex < impl.getSize())
	{
		retVal = true;
	}

	return retVal;
}

template <typename T>
T& ArrayList<T>::Iterator::peekNext()
{
	if (!hasNext())
	{
		string msg = "No more elements in ArrayList::Iterator::peekNext()";
		throw new NoMoreElementsError(msg);
	}

	return impl.get(nextIndex);
}

template <typename T>
T& ArrayList<T>::Iterator::next()
{
	if (!hasNext())
	{
		string msg = "No more elements in ArrayList::Iterator::next()";
		throw new NoMoreElementsError(msg);
	}

	return impl.get(nextIndex++);
}
<|endoftext|>


<commit_before>/***************************************************************************
    copyright            : (C) 2002 - 2008 by Scott Wheeler
    email                : wheeler@kde.org
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License version   *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
 *   02110-1301  USA                                                       *
 *                                                                         *
 *   Alternatively, this file is available under the Mozilla Public        *
 *   License Version 1.1.  You may obtain a copy of the License at         *
 *   http://www.mozilla.org/MPL/                                           *
 ***************************************************************************/

#include "tfilestream.h"
#include "tstring.h"
#include "tdebug.h"

#ifdef _WIN32
# include <windows.h>
#else
# include <stdio.h>
# include <unistd.h>
#endif

using namespace TagLib;

namespace
{
#ifdef _WIN32

  // Uses Win32 native API instead of POSIX API to reduce the resource consumption.

  typedef FileName FileNameHandle;
  typedef HANDLE FileHandle;

  const FileHandle InvalidFileHandle = INVALID_HANDLE_VALUE;

  FileHandle openFile(const FileName &path, bool readOnly)
  {
    const DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);

	if(!path.wstr().empty())
#if (_WIN32_WINNT >= 0x0602)
	  return CreateFile2(path.wstr().c_str(), access, FILE_SHARE_READ, OPEN_EXISTING, NULL);
#else
	  return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
#endif
	else if(!path.str().empty())
#if (_WIN32_WINNT >= 0x0602)
	  return CreateFile2(path.toString().toCWString(), access, FILE_SHARE_READ, OPEN_EXISTING, NULL);
#else
	  return CreateFileA(path.str().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
#endif
    else
      return InvalidFileHandle;
  }

  void closeFile(FileHandle file)
  {
    CloseHandle(file);
  }

  size_t readFile(FileHandle file, ByteVector &buffer)
  {
    DWORD length;
    if(ReadFile(file, buffer.data(), static_cast<DWORD>(buffer.size()), &length, NULL))
      return static_cast<size_t>(length);
    else
      return 0;
  }

  size_t writeFile(FileHandle file, const ByteVector &buffer)
  {
    DWORD length;
    if(WriteFile(file, buffer.data(), static_cast<DWORD>(buffer.size()), &length, NULL))
      return static_cast<size_t>(length);
    else
      return 0;
  }

#else   // _WIN32

  struct FileNameHandle : public std::string
  {
    FileNameHandle(FileName name) : std::string(name) {}
    operator FileName () const { return c_str(); }
  };

  typedef FILE* FileHandle;

  const FileHandle InvalidFileHandle = 0;

  FileHandle openFile(const FileName &path, bool readOnly)
  {
    return fopen(path, readOnly ? "rb" : "rb+");
  }

  void closeFile(FileHandle file)
  {
    fclose(file);
  }

  size_t readFile(FileHandle file, ByteVector &buffer)
  {
    return fread(buffer.data(), sizeof(char), buffer.size(), file);
  }

  size_t writeFile(FileHandle file, const ByteVector &buffer)
  {
    return fwrite(buffer.data(), sizeof(char), buffer.size(), file);
  }

#endif  // _WIN32
}

class FileStream::FileStreamPrivate
{
public:
  FileStreamPrivate(const FileName &fileName)
    : file(InvalidFileHandle)
    , name(fileName)
    , readOnly(true)
  {
  }

  FileHandle file;
  FileNameHandle name;
  bool readOnly;
};

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

FileStream::FileStream(FileName fileName, bool openReadOnly)
  : d(new FileStreamPrivate(fileName))
{
  // First try with read / write mode, if that fails, fall back to read only.

  if(!openReadOnly)
    d->file = openFile(fileName, false);

  if(d->file != InvalidFileHandle)
    d->readOnly = false;
  else
    d->file = openFile(fileName, true);

  if(d->file == InvalidFileHandle)
  {
# ifdef _WIN32
    debug("Could not open file " + fileName.toString());
# else
    debug("Could not open file " + String(static_cast<const char *>(d->name)));
# endif
  }
}

FileStream::~FileStream()
{
  if(isOpen())
    closeFile(d->file);

  delete d;
}

FileName FileStream::name() const
{
  return d->name;
}

ByteVector FileStream::readBlock(unsigned long length)
{
  if(!isOpen()) {
    debug("FileStream::readBlock() -- invalid file.");
    return ByteVector();
  }

  if(length == 0)
    return ByteVector();

  const unsigned long streamLength = static_cast<unsigned long>(FileStream::length());
  if(length > bufferSize() && length > streamLength)
    length = streamLength;

  ByteVector buffer(static_cast<unsigned int>(length));

  const size_t count = readFile(d->file, buffer);
  buffer.resize(static_cast<unsigned int>(count));

  return buffer;
}

void FileStream::writeBlock(const ByteVector &data)
{
  if(!isOpen()) {
    debug("FileStream::writeBlock() -- invalid file.");
    return;
  }

  if(readOnly()) {
    debug("FileStream::writeBlock() -- read only file.");
    return;
  }

  writeFile(d->file, data);
}

void FileStream::insert(const ByteVector &data, unsigned long start, unsigned long replace)
{
  if(!isOpen()) {
    debug("FileStream::insert() -- invalid file.");
    return;
  }

  if(readOnly()) {
    debug("FileStream::insert() -- read only file.");
    return;
  }

  if(data.size() == replace) {
    seek(start);
    writeBlock(data);
    return;
  }
  else if(data.size() < replace) {
    seek(start);
    writeBlock(data);
    removeBlock(start + data.size(), replace - data.size());
    return;
  }

  // Woohoo!  Faster (about 20%) than id3lib at last.  I had to get hardcore
  // and avoid TagLib's high level API for rendering just copying parts of
  // the file that don't contain tag data.
  //
  // Now I'll explain the steps in this ugliness:

  // First, make sure that we're working with a buffer that is longer than
  // the *differnce* in the tag sizes.  We want to avoid overwriting parts
  // that aren't yet in memory, so this is necessary.

  unsigned long bufferLength = bufferSize();

  while(data.size() - replace > bufferLength)
    bufferLength += bufferSize();

  // Set where to start the reading and writing.

  long readPosition = start + replace;
  long writePosition = start;

  ByteVector buffer = data;
  ByteVector aboutToOverwrite(static_cast<unsigned int>(bufferLength));

  while(true)
  {
    // Seek to the current read position and read the data that we're about
    // to overwrite.  Appropriately increment the readPosition.

    seek(readPosition);
    const size_t bytesRead = readFile(d->file, aboutToOverwrite);
    aboutToOverwrite.resize(bytesRead);
    readPosition += bufferLength;

    // Check to see if we just read the last block.  We need to call clear()
    // if we did so that the last write succeeds.

    if(bytesRead < bufferLength)
      clear();

    // Seek to the write position and write our buffer.  Increment the
    // writePosition.

    seek(writePosition);
    writeBlock(buffer);

    // We hit the end of the file.

    if(bytesRead == 0)
      break;

    writePosition += buffer.size();

    // Make the current buffer the data that we read in the beginning.

    buffer = aboutToOverwrite;
  }
}

void FileStream::removeBlock(unsigned long start, unsigned long length)
{
  if(!isOpen()) {
    debug("FileStream::removeBlock() -- invalid file.");
    return;
  }

  unsigned long bufferLength = bufferSize();

  long readPosition = start + length;
  long writePosition = start;

  ByteVector buffer(static_cast<unsigned int>(bufferLength));

  for(size_t bytesRead = -1; bytesRead != 0;)
  {
    seek(readPosition);
    bytesRead = readFile(d->file, buffer);
    readPosition += bytesRead;

    // Check to see if we just read the last block.  We need to call clear()
    // if we did so that the last write succeeds.

    if(bytesRead < buffer.size()) {
      clear();
      buffer.resize(bytesRead);
    }

    seek(writePosition);
    writeFile(d->file, buffer);

    writePosition += bytesRead;
  }

  truncate(writePosition);
}

bool FileStream::readOnly() const
{
  return d->readOnly;
}

bool FileStream::isOpen() const
{
  return (d->file != InvalidFileHandle);
}

void FileStream::seek(long offset, Position p)
{
  if(!isOpen()) {
    debug("FileStream::seek() -- invalid file.");
    return;
  }

#ifdef _WIN32

  DWORD whence;
  switch(p) {
  case Beginning:
    whence = FILE_BEGIN;
    break;
  case Current:
    whence = FILE_CURRENT;
    break;
  case End:
    whence = FILE_END;
    break;
  default:
    debug("FileStream::seek() -- Invalid Position value.");
    return;
  }

  SetLastError(NO_ERROR);
  SetFilePointer(d->file, offset, NULL, whence);

  const int lastError = GetLastError();
  if(lastError != NO_ERROR && lastError != ERROR_NEGATIVE_SEEK)
    debug("FileStream::seek() -- Failed to set the file pointer.");

#else

  int whence;
  switch(p) {
  case Beginning:
    whence = SEEK_SET;
    break;
  case Current:
    whence = SEEK_CUR;
    break;
  case End:
    whence = SEEK_END;
    break;
  default:
    debug("FileStream::seek() -- Invalid Position value.");
    return;
  }

  fseek(d->file, offset, whence);

#endif
}

void FileStream::clear()
{
#ifdef _WIN32

  // NOP

#else

  clearerr(d->file);

#endif
}

long FileStream::tell() const
{
#ifdef _WIN32

  SetLastError(NO_ERROR);
  const DWORD position = SetFilePointer(d->file, 0, NULL, FILE_CURRENT);
  if(GetLastError() == NO_ERROR) {
    return static_cast<long>(position);
  }
  else {
    debug("FileStream::tell() -- Failed to get the file pointer.");
    return 0;
  }

#else

  return ftell(d->file);

#endif
}

long FileStream::length()
{
  if(!isOpen()) {
    debug("FileStream::length() -- invalid file.");
    return 0;
  }

#ifdef _WIN32

  SetLastError(NO_ERROR);
#if (_WIN32_WINNT >= 0x0602)
  LARGE_INTEGER fSize;
  GetFileSizeEx(d->file, &fSize);
  LONGLONG fileSize = fSize.QuadPart;
#else
  const DWORD fileSize = GetFileSize(d->file, NULL);
#endif
  if(GetLastError() == NO_ERROR) {
    return static_cast<long>(fileSize);
  }
  else {
    debug("FileStream::length() -- Failed to get the file size.");
    return 0;
  }

#else

  const long curpos = tell();

  seek(0, End);
  const long endpos = tell();

  seek(curpos, Beginning);

  return endpos;

#endif
}

////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////

void FileStream::truncate(long length)
{
#ifdef _WIN32

  const long currentPos = tell();

  seek(length);

  SetLastError(NO_ERROR);
  SetEndOfFile(d->file);
  if(GetLastError() != NO_ERROR) {
    debug("FileStream::truncate() -- Failed to truncate the file.");
  }

  seek(currentPos);

#else

  const int error = ftruncate(fileno(d->file), length);
  if(error != 0) {
    debug("FileStream::truncate() -- Coundn't truncate the file.");
  }

#endif
}

unsigned int FileStream::bufferSize()
{
  return 1024;
}
<commit_msg>Better define guards<commit_after>/***************************************************************************
    copyright            : (C) 2002 - 2008 by Scott Wheeler
    email                : wheeler@kde.org
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License version   *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
 *   02110-1301  USA                                                       *
 *                                                                         *
 *   Alternatively, this file is available under the Mozilla Public        *
 *   License Version 1.1.  You may obtain a copy of the License at         *
 *   http://www.mozilla.org/MPL/                                           *
 ***************************************************************************/

#include "tfilestream.h"
#include "tstring.h"
#include "tdebug.h"

#ifdef _WIN32
# include <windows.h>
#else
# include <stdio.h>
# include <unistd.h>
#endif

using namespace TagLib;

namespace
{
#ifdef _WIN32

  // Uses Win32 native API instead of POSIX API to reduce the resource consumption.

  typedef FileName FileNameHandle;
  typedef HANDLE FileHandle;

  const FileHandle InvalidFileHandle = INVALID_HANDLE_VALUE;

  FileHandle openFile(const FileName &path, bool readOnly)
  {
    const DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);

	if(!path.wstr().empty())
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)
	  return CreateFile2(path.wstr().c_str(), access, FILE_SHARE_READ, OPEN_EXISTING, NULL);
#else
	  return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
#endif
	else if(!path.str().empty())
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)
	  return CreateFile2(path.toString().toCWString(), access, FILE_SHARE_READ, OPEN_EXISTING, NULL);
#else
	  return CreateFileA(path.str().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
#endif
    else
      return InvalidFileHandle;
  }

  void closeFile(FileHandle file)
  {
    CloseHandle(file);
  }

  size_t readFile(FileHandle file, ByteVector &buffer)
  {
    DWORD length;
    if(ReadFile(file, buffer.data(), static_cast<DWORD>(buffer.size()), &length, NULL))
      return static_cast<size_t>(length);
    else
      return 0;
  }

  size_t writeFile(FileHandle file, const ByteVector &buffer)
  {
    DWORD length;
    if(WriteFile(file, buffer.data(), static_cast<DWORD>(buffer.size()), &length, NULL))
      return static_cast<size_t>(length);
    else
      return 0;
  }

#else   // _WIN32

  struct FileNameHandle : public std::string
  {
    FileNameHandle(FileName name) : std::string(name) {}
    operator FileName () const { return c_str(); }
  };

  typedef FILE* FileHandle;

  const FileHandle InvalidFileHandle = 0;

  FileHandle openFile(const FileName &path, bool readOnly)
  {
    return fopen(path, readOnly ? "rb" : "rb+");
  }

  void closeFile(FileHandle file)
  {
    fclose(file);
  }

  size_t readFile(FileHandle file, ByteVector &buffer)
  {
    return fread(buffer.data(), sizeof(char), buffer.size(), file);
  }

  size_t writeFile(FileHandle file, const ByteVector &buffer)
  {
    return fwrite(buffer.data(), sizeof(char), buffer.size(), file);
  }

#endif  // _WIN32
}

class FileStream::FileStreamPrivate
{
public:
  FileStreamPrivate(const FileName &fileName)
    : file(InvalidFileHandle)
    , name(fileName)
    , readOnly(true)
  {
  }

  FileHandle file;
  FileNameHandle name;
  bool readOnly;
};

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

FileStream::FileStream(FileName fileName, bool openReadOnly)
  : d(new FileStreamPrivate(fileName))
{
  // First try with read / write mode, if that fails, fall back to read only.

  if(!openReadOnly)
    d->file = openFile(fileName, false);

  if(d->file != InvalidFileHandle)
    d->readOnly = false;
  else
    d->file = openFile(fileName, true);

  if(d->file == InvalidFileHandle)
  {
# ifdef _WIN32
    debug("Could not open file " + fileName.toString());
# else
    debug("Could not open file " + String(static_cast<const char *>(d->name)));
# endif
  }
}

FileStream::~FileStream()
{
  if(isOpen())
    closeFile(d->file);

  delete d;
}

FileName FileStream::name() const
{
  return d->name;
}

ByteVector FileStream::readBlock(unsigned long length)
{
  if(!isOpen()) {
    debug("FileStream::readBlock() -- invalid file.");
    return ByteVector();
  }

  if(length == 0)
    return ByteVector();

  const unsigned long streamLength = static_cast<unsigned long>(FileStream::length());
  if(length > bufferSize() && length > streamLength)
    length = streamLength;

  ByteVector buffer(static_cast<unsigned int>(length));

  const size_t count = readFile(d->file, buffer);
  buffer.resize(static_cast<unsigned int>(count));

  return buffer;
}

void FileStream::writeBlock(const ByteVector &data)
{
  if(!isOpen()) {
    debug("FileStream::writeBlock() -- invalid file.");
    return;
  }

  if(readOnly()) {
    debug("FileStream::writeBlock() -- read only file.");
    return;
  }

  writeFile(d->file, data);
}

void FileStream::insert(const ByteVector &data, unsigned long start, unsigned long replace)
{
  if(!isOpen()) {
    debug("FileStream::insert() -- invalid file.");
    return;
  }

  if(readOnly()) {
    debug("FileStream::insert() -- read only file.");
    return;
  }

  if(data.size() == replace) {
    seek(start);
    writeBlock(data);
    return;
  }
  else if(data.size() < replace) {
    seek(start);
    writeBlock(data);
    removeBlock(start + data.size(), replace - data.size());
    return;
  }

  // Woohoo!  Faster (about 20%) than id3lib at last.  I had to get hardcore
  // and avoid TagLib's high level API for rendering just copying parts of
  // the file that don't contain tag data.
  //
  // Now I'll explain the steps in this ugliness:

  // First, make sure that we're working with a buffer that is longer than
  // the *differnce* in the tag sizes.  We want to avoid overwriting parts
  // that aren't yet in memory, so this is necessary.

  unsigned long bufferLength = bufferSize();

  while(data.size() - replace > bufferLength)
    bufferLength += bufferSize();

  // Set where to start the reading and writing.

  long readPosition = start + replace;
  long writePosition = start;

  ByteVector buffer = data;
  ByteVector aboutToOverwrite(static_cast<unsigned int>(bufferLength));

  while(true)
  {
    // Seek to the current read position and read the data that we're about
    // to overwrite.  Appropriately increment the readPosition.

    seek(readPosition);
    const size_t bytesRead = readFile(d->file, aboutToOverwrite);
    aboutToOverwrite.resize(bytesRead);
    readPosition += bufferLength;

    // Check to see if we just read the last block.  We need to call clear()
    // if we did so that the last write succeeds.

    if(bytesRead < bufferLength)
      clear();

    // Seek to the write position and write our buffer.  Increment the
    // writePosition.

    seek(writePosition);
    writeBlock(buffer);

    // We hit the end of the file.

    if(bytesRead == 0)
      break;

    writePosition += buffer.size();

    // Make the current buffer the data that we read in the beginning.

    buffer = aboutToOverwrite;
  }
}

void FileStream::removeBlock(unsigned long start, unsigned long length)
{
  if(!isOpen()) {
    debug("FileStream::removeBlock() -- invalid file.");
    return;
  }

  unsigned long bufferLength = bufferSize();

  long readPosition = start + length;
  long writePosition = start;

  ByteVector buffer(static_cast<unsigned int>(bufferLength));

  for(size_t bytesRead = -1; bytesRead != 0;)
  {
    seek(readPosition);
    bytesRead = readFile(d->file, buffer);
    readPosition += bytesRead;

    // Check to see if we just read the last block.  We need to call clear()
    // if we did so that the last write succeeds.

    if(bytesRead < buffer.size()) {
      clear();
      buffer.resize(bytesRead);
    }

    seek(writePosition);
    writeFile(d->file, buffer);

    writePosition += bytesRead;
  }

  truncate(writePosition);
}

bool FileStream::readOnly() const
{
  return d->readOnly;
}

bool FileStream::isOpen() const
{
  return (d->file != InvalidFileHandle);
}

void FileStream::seek(long offset, Position p)
{
  if(!isOpen()) {
    debug("FileStream::seek() -- invalid file.");
    return;
  }

#ifdef _WIN32

  DWORD whence;
  switch(p) {
  case Beginning:
    whence = FILE_BEGIN;
    break;
  case Current:
    whence = FILE_CURRENT;
    break;
  case End:
    whence = FILE_END;
    break;
  default:
    debug("FileStream::seek() -- Invalid Position value.");
    return;
  }

  SetLastError(NO_ERROR);
  SetFilePointer(d->file, offset, NULL, whence);

  const int lastError = GetLastError();
  if(lastError != NO_ERROR && lastError != ERROR_NEGATIVE_SEEK)
    debug("FileStream::seek() -- Failed to set the file pointer.");

#else

  int whence;
  switch(p) {
  case Beginning:
    whence = SEEK_SET;
    break;
  case Current:
    whence = SEEK_CUR;
    break;
  case End:
    whence = SEEK_END;
    break;
  default:
    debug("FileStream::seek() -- Invalid Position value.");
    return;
  }

  fseek(d->file, offset, whence);

#endif
}

void FileStream::clear()
{
#ifdef _WIN32

  // NOP

#else

  clearerr(d->file);

#endif
}

long FileStream::tell() const
{
#ifdef _WIN32

  SetLastError(NO_ERROR);
  const DWORD position = SetFilePointer(d->file, 0, NULL, FILE_CURRENT);
  if(GetLastError() == NO_ERROR) {
    return static_cast<long>(position);
  }
  else {
    debug("FileStream::tell() -- Failed to get the file pointer.");
    return 0;
  }

#else

  return ftell(d->file);

#endif
}

long FileStream::length()
{
  if(!isOpen()) {
    debug("FileStream::length() -- invalid file.");
    return 0;
  }

#ifdef _WIN32

  SetLastError(NO_ERROR);
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)
  LARGE_INTEGER fSize;
  GetFileSizeEx(d->file, &fSize);
  LONGLONG fileSize = fSize.QuadPart;
#else
  const DWORD fileSize = GetFileSize(d->file, NULL);
#endif
  if(GetLastError() == NO_ERROR) {
    return static_cast<long>(fileSize);
  }
  else {
    debug("FileStream::length() -- Failed to get the file size.");
    return 0;
  }

#else

  const long curpos = tell();

  seek(0, End);
  const long endpos = tell();

  seek(curpos, Beginning);

  return endpos;

#endif
}

////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////

void FileStream::truncate(long length)
{
#ifdef _WIN32

  const long currentPos = tell();

  seek(length);

  SetLastError(NO_ERROR);
  SetEndOfFile(d->file);
  if(GetLastError() != NO_ERROR) {
    debug("FileStream::truncate() -- Failed to truncate the file.");
  }

  seek(currentPos);

#else

  const int error = ftruncate(fileno(d->file), length);
  if(error != 0) {
    debug("FileStream::truncate() -- Coundn't truncate the file.");
  }

#endif
}

unsigned int FileStream::bufferSize()
{
  return 1024;
}
<|endoftext|>


<commit_before>#include "b2entity.h"

B2Entity::B2Entity(int width, int height, unsigned int textureID, b2World* world) : Sprite::Sprite(width, height, textureID) {
	// Save all of the variables received from the constructor
	this->world = world;

	// Give all of the variables a value because it is bad to leave it not initialized
	fixture = nullptr;
	body = nullptr;
	shape = Shape::box;
	colliderWidth = 0;
	colliderHeight = 0;
	debugColor = glm::vec3(1, 1, 1);
	colliderPivot = glm::vec2(-0.5f, 0.0f);
	filter = 0;
}

B2Entity::~B2Entity() {
	// If the body was created make sure to delete everything as well
	if (body != nullptr) {
		body->DestroyFixture(fixture);
		world->DestroyBody(body);
	}
}

// This function is normally called by the parent
void B2Entity::UpdateChilderen(Entity * parent, double deltaTime)
{
	// Check if the parent does not equals NULL and set this's position/angle and scale
	if (parent != NULL) {
		model = parent->GetModelMatrix();
		model = glm::translate(model, glm::vec3(localPosition.x, localPosition.y, 0.0f));
		model = glm::rotate(model, localAngle, glm::vec3(0.0f, 0.0f, 1.0f));
		// The third row is the position of the
		this->position = model[3];
		// The first two values in the mat4 can be used to get the z-rotation according to: https://stackoverflow.com/questions/39251412/get-the-angle-from-a-rotated-matrix-using-glm
		this->angle = glm::atan(model[0][1], model[0][0]);
	}
	else {
		// If the parent is null set the global position/angle/scale equal to the localPosition of this B2Entity
		this->position = this->localPosition;
		this->angle = this->localAngle;
		model = glm::mat4();
		model = glm::translate(model, glm::vec3(position.x, position.y, 0.0f));
		model = glm::rotate(model, angle, glm::vec3(0.0f, 0.0f, 1.0f));
	}
	// If the body is intialized update the position and angle of the body
	if (this->body != nullptr) {
		body->SetTransform(b2Vec2(this->position.x * p2m, this->position.y * p2m), this->angle);
	}
	// Update and draw all of the childeren and their childeren
	for (int i = 0; i < entities.size(); i++) {
		entities[i]->Draw();
		entities[i]->Update(deltaTime);
		entities[i]->UpdateChilderen(this, deltaTime);
	}
}

void B2Entity::DrawChilderen(Entity * parent)
{
	// Check if the parent does not equals NULL and set this's position/angle and scale
	if (parent != NULL) {
		model = parent->GetModelMatrix();
		model = glm::translate(model, glm::vec3(localPosition.x, localPosition.y, 0.0f));
		model = glm::rotate(model, localAngle, glm::vec3(0.0f, 0.0f, 1.0f));
		// The third row is the position of the
		this->position = model[3];
		// The first two values in the mat4 can be used to get the z-rotation according to: https://stackoverflow.com/questions/39251412/get-the-angle-from-a-rotated-matrix-using-glm
		this->angle = glm::atan(model[0][1], model[0][0]);
	}
	else {
		// If the parent is null set the global position/angle/scale equal to the localPosition of this B2Entity
		this->position = this->localPosition;
		this->angle = this->localAngle;
		model = glm::mat4();
		model = glm::translate(model, glm::vec3(position.x, position.y, 0.0f));
		model = glm::rotate(model, angle, glm::vec3(0.0f, 0.0f, 1.0f));
	}
	// If the body is intialized update the position and angle of the body
	if (this->body != nullptr) {
		body->SetTransform(b2Vec2(this->position.x * p2m, this->position.y * p2m), this->angle);
	}
	// Update and draw all of the childeren and their childeren
	for (int i = 0; i < entities.size(); i++) {
		entities[i]->Draw();
		entities[i]->DrawChilderen(this);
	}
}

void B2Entity::Draw() {
	renderer->Submit(this);
	if (body != nullptr) {
		DebugRenderer::Submit(this);
	}
}

void B2Entity::CreateBoxCollider(int w, int h, glm::vec2 pivot, bool dynamic, bool sensor) {
	if (pivot.x != 0.0f) {
		std::cout << "The pivot = " << pivot.x << std::endl;
	}
	colliderPivot = pivot;
	shape = Shape::box;
	// If the body was created make sure to delete everything as well
	if (body != nullptr) {
		body->DestroyFixture(fixture);
		world->DestroyBody(body);
	}
	// Save the w and h for later use
	colliderWidth = w;
	colliderHeight = h;
	// Step 1 defina a body
	b2BodyDef bodydef;
	bodydef.position.Set(0.0f, 0.0f);
	bodydef.fixedRotation = true;
	if (dynamic) {
		bodydef.type = b2_dynamicBody;
	}
	else {
		bodydef.type = b2_staticBody;
	}

	// Step 2 create a body
	body = world->CreateBody(&bodydef);

	// Step 3 create shape
	b2PolygonShape shape;
	// pivot has to go times -1 because box2d sets the pivot point the otherway around then I want it
	pivot *= -1;
	// the reason for dividing by 2 is because box2D draws from the center
	shape.SetAsBox(w / 2 * p2m, h / 2 * p2m, b2Vec2((pivot.x * width * p2m) * -1, (pivot.y * height * p2m) * -1), 0.0f);
	// step 4 create fixture
	b2FixtureDef fixtureDef;
	fixtureDef.shape = &shape;
	fixtureDef.density = 1.0;
	fixtureDef.friction = 0.3f;
	fixtureDef.restitution = 0.5f;
	fixture = body->CreateFixture(&fixtureDef);
	if (sensor) {
		fixture->SetSensor(true);
	}
	fixture->SetUserData(this);
	body->SetActive(true);
}

void B2Entity::CreateCircleCollider(int radius, bool dynamic, bool sensor)
{
	shape = Shape::circle;
	// If the body was created make sure to delete everything as well
	if (body != nullptr) {
		body->DestroyFixture(fixture);
		world->DestroyBody(body);
	}
	// Save the w and h for later use
	colliderWidth = radius;
	colliderHeight = radius;
	// Step 1 defina a body
	b2BodyDef bodydef;
	bodydef.position.Set(0.0f, 0.0f);
	bodydef.fixedRotation = true;
	if (dynamic) {
		bodydef.type = b2_dynamicBody;
	}
	else {
		bodydef.type = b2_staticBody;
	}

	// Step 2 create a body
	body = world->CreateBody(&bodydef);

	// Step 3 create shape
	b2CircleShape shape;
	shape.m_radius = radius * p2m;
	shape.m_type = shape.e_circle;
	// step 4 create fixture
	b2FixtureDef fixtureDef;
	fixtureDef.shape = &shape;
	fixtureDef.density = 1.0;
	fixtureDef.friction = 0.3f;
	fixtureDef.restitution = 0.5f;
	fixture = body->CreateFixture(&fixtureDef);
	if (sensor) {
		fixture->SetSensor(true);
	}
	fixture->SetUserData(this);
	body->SetActive(true);
}

void B2Entity::SetDebugColor(glm::vec3 color)
{
	debugColor = color;
}

glm::vec2 B2Entity::ApplyVelocityB2body(glm::vec2 velocity)
{
	// Set the velocity to a b2Vec2 and apply it
	b2Vec2 vel = b2Vec2(velocity.x, velocity.y);
	body->SetLinearVelocity(vel);
	// Receive the new position and return it in world space
	glm::vec2 pos = glm::vec2(body->GetPosition().x * m2p, body->GetPosition().y * m2p);
	return pos;
}

int B2Entity::GetColliderWidth()
{
	return colliderWidth;
}

int B2Entity::GetColliderHeight()
{
	return colliderHeight;
}

void B2Entity::AddContact(B2Entity* contact) {
	this->contacts.push_back(contact);
}

void B2Entity::RemoveContact(B2Entity* contact) {
	// Iterate through all of the contacts and find the right contact to delete
	std::vector<B2Entity*>::iterator it = contacts.begin();
	while (it != contacts.end()) {
		if ((*it) == contact) {
			it = contacts.erase(it);
			return;
		}
		++it;
	}
	// This cout line should never be called if it is something might be very wrong
	std::cout << "You tried to remove a contact, but that contact could not be found!" << std::endl;
}

bool B2Entity::Contact(B2Entity * contact)
{
	int count = contacts.size();
	for (int i = 0; i < count; i++) {
		if (contacts[i] == contact) {
			return true;
		}
	}
	return false;
}

std::vector<B2Entity*> B2Entity::GetAllContacts()
{
	return contacts;
}

void B2Entity::SetActive(bool active) {
	// Set active or deactive but only if the body is initialized
	if (body != NULL) {
		body->SetActive(active);
	}
}<commit_msg>removed a cout<commit_after>#include "b2entity.h"

B2Entity::B2Entity(int width, int height, unsigned int textureID, b2World* world) : Sprite::Sprite(width, height, textureID) {
	// Save all of the variables received from the constructor
	this->world = world;

	// Give all of the variables a value because it is bad to leave it not initialized
	fixture = nullptr;
	body = nullptr;
	shape = Shape::box;
	colliderWidth = 0;
	colliderHeight = 0;
	debugColor = glm::vec3(1, 1, 1);
	colliderPivot = glm::vec2(-0.5f, 0.0f);
	filter = 0;
}

B2Entity::~B2Entity() {
	// If the body was created make sure to delete everything as well
	if (body != nullptr) {
		body->DestroyFixture(fixture);
		world->DestroyBody(body);
	}
}

// This function is normally called by the parent
void B2Entity::UpdateChilderen(Entity * parent, double deltaTime)
{
	// Check if the parent does not equals NULL and set this's position/angle and scale
	if (parent != NULL) {
		model = parent->GetModelMatrix();
		model = glm::translate(model, glm::vec3(localPosition.x, localPosition.y, 0.0f));
		model = glm::rotate(model, localAngle, glm::vec3(0.0f, 0.0f, 1.0f));
		// The third row is the position of the
		this->position = model[3];
		// The first two values in the mat4 can be used to get the z-rotation according to: https://stackoverflow.com/questions/39251412/get-the-angle-from-a-rotated-matrix-using-glm
		this->angle = glm::atan(model[0][1], model[0][0]);
	}
	else {
		// If the parent is null set the global position/angle/scale equal to the localPosition of this B2Entity
		this->position = this->localPosition;
		this->angle = this->localAngle;
		model = glm::mat4();
		model = glm::translate(model, glm::vec3(position.x, position.y, 0.0f));
		model = glm::rotate(model, angle, glm::vec3(0.0f, 0.0f, 1.0f));
	}
	// If the body is intialized update the position and angle of the body
	if (this->body != nullptr) {
		body->SetTransform(b2Vec2(this->position.x * p2m, this->position.y * p2m), this->angle);
	}
	// Update and draw all of the childeren and their childeren
	for (int i = 0; i < entities.size(); i++) {
		entities[i]->Draw();
		entities[i]->Update(deltaTime);
		entities[i]->UpdateChilderen(this, deltaTime);
	}
}

void B2Entity::DrawChilderen(Entity * parent)
{
	// Check if the parent does not equals NULL and set this's position/angle and scale
	if (parent != NULL) {
		model = parent->GetModelMatrix();
		model = glm::translate(model, glm::vec3(localPosition.x, localPosition.y, 0.0f));
		model = glm::rotate(model, localAngle, glm::vec3(0.0f, 0.0f, 1.0f));
		// The third row is the position of the
		this->position = model[3];
		// The first two values in the mat4 can be used to get the z-rotation according to: https://stackoverflow.com/questions/39251412/get-the-angle-from-a-rotated-matrix-using-glm
		this->angle = glm::atan(model[0][1], model[0][0]);
	}
	else {
		// If the parent is null set the global position/angle/scale equal to the localPosition of this B2Entity
		this->position = this->localPosition;
		this->angle = this->localAngle;
		model = glm::mat4();
		model = glm::translate(model, glm::vec3(position.x, position.y, 0.0f));
		model = glm::rotate(model, angle, glm::vec3(0.0f, 0.0f, 1.0f));
	}
	// If the body is intialized update the position and angle of the body
	if (this->body != nullptr) {
		body->SetTransform(b2Vec2(this->position.x * p2m, this->position.y * p2m), this->angle);
	}
	// Update and draw all of the childeren and their childeren
	for (int i = 0; i < entities.size(); i++) {
		entities[i]->Draw();
		entities[i]->DrawChilderen(this);
	}
}

void B2Entity::Draw() {
	renderer->Submit(this);
	if (body != nullptr) {
		DebugRenderer::Submit(this);
	}
}

void B2Entity::CreateBoxCollider(int w, int h, glm::vec2 pivot, bool dynamic, bool sensor) {
	/*if (pivot.x != 0.0f) {
		std::cout << "The pivot = " << pivot.x << std::endl;
	}*/
	colliderPivot = pivot;
	shape = Shape::box;
	// If the body was created make sure to delete everything as well
	if (body != nullptr) {
		body->DestroyFixture(fixture);
		world->DestroyBody(body);
	}
	// Save the w and h for later use
	colliderWidth = w;
	colliderHeight = h;
	// Step 1 defina a body
	b2BodyDef bodydef;
	bodydef.position.Set(0.0f, 0.0f);
	bodydef.fixedRotation = true;
	if (dynamic) {
		bodydef.type = b2_dynamicBody;
	}
	else {
		bodydef.type = b2_staticBody;
	}

	// Step 2 create a body
	body = world->CreateBody(&bodydef);

	// Step 3 create shape
	b2PolygonShape shape;
	// pivot has to go times -1 because box2d sets the pivot point the otherway around then I want it
	pivot *= -1;
	// the reason for dividing by 2 is because box2D draws from the center
	shape.SetAsBox(w / 2 * p2m, h / 2 * p2m, b2Vec2((pivot.x * width * p2m) * -1, (pivot.y * height * p2m) * -1), 0.0f);
	// step 4 create fixture
	b2FixtureDef fixtureDef;
	fixtureDef.shape = &shape;
	fixtureDef.density = 1.0;
	fixtureDef.friction = 0.3f;
	fixtureDef.restitution = 0.5f;
	fixture = body->CreateFixture(&fixtureDef);
	if (sensor) {
		fixture->SetSensor(true);
	}
	fixture->SetUserData(this);
	body->SetActive(true);
}

void B2Entity::CreateCircleCollider(int radius, bool dynamic, bool sensor)
{
	shape = Shape::circle;
	// If the body was created make sure to delete everything as well
	if (body != nullptr) {
		body->DestroyFixture(fixture);
		world->DestroyBody(body);
	}
	// Save the w and h for later use
	colliderWidth = radius;
	colliderHeight = radius;
	// Step 1 defina a body
	b2BodyDef bodydef;
	bodydef.position.Set(0.0f, 0.0f);
	bodydef.fixedRotation = true;
	if (dynamic) {
		bodydef.type = b2_dynamicBody;
	}
	else {
		bodydef.type = b2_staticBody;
	}

	// Step 2 create a body
	body = world->CreateBody(&bodydef);

	// Step 3 create shape
	b2CircleShape shape;
	shape.m_radius = radius * p2m;
	shape.m_type = shape.e_circle;
	// step 4 create fixture
	b2FixtureDef fixtureDef;
	fixtureDef.shape = &shape;
	fixtureDef.density = 1.0;
	fixtureDef.friction = 0.3f;
	fixtureDef.restitution = 0.5f;
	fixture = body->CreateFixture(&fixtureDef);
	if (sensor) {
		fixture->SetSensor(true);
	}
	fixture->SetUserData(this);
	body->SetActive(true);
}

void B2Entity::SetDebugColor(glm::vec3 color)
{
	debugColor = color;
}

glm::vec2 B2Entity::ApplyVelocityB2body(glm::vec2 velocity)
{
	// Set the velocity to a b2Vec2 and apply it
	b2Vec2 vel = b2Vec2(velocity.x, velocity.y);
	body->SetLinearVelocity(vel);
	// Receive the new position and return it in world space
	glm::vec2 pos = glm::vec2(body->GetPosition().x * m2p, body->GetPosition().y * m2p);
	return pos;
}

int B2Entity::GetColliderWidth()
{
	return colliderWidth;
}

int B2Entity::GetColliderHeight()
{
	return colliderHeight;
}

void B2Entity::AddContact(B2Entity* contact) {
	this->contacts.push_back(contact);
}

void B2Entity::RemoveContact(B2Entity* contact) {
	// Iterate through all of the contacts and find the right contact to delete
	std::vector<B2Entity*>::iterator it = contacts.begin();
	while (it != contacts.end()) {
		if ((*it) == contact) {
			it = contacts.erase(it);
			return;
		}
		++it;
	}
	// This cout line should never be called if it is something might be very wrong
	std::cout << "You tried to remove a contact, but that contact could not be found!" << std::endl;
}

bool B2Entity::Contact(B2Entity * contact)
{
	int count = contacts.size();
	for (int i = 0; i < count; i++) {
		if (contacts[i] == contact) {
			return true;
		}
	}
	return false;
}

std::vector<B2Entity*> B2Entity::GetAllContacts()
{
	return contacts;
}

void B2Entity::SetActive(bool active) {
	// Set active or deactive but only if the body is initialized
	if (body != NULL) {
		body->SetActive(active);
	}
}<|endoftext|>