<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/events/gestures/gesture_recognizer_impl.h"

#include <limits>

#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_switches.h"
#include "ui/events/event_utils.h"
#include "ui/events/gestures/gesture_configuration.h"
#include "ui/events/gestures/gesture_sequence.h"
#include "ui/events/gestures/gesture_types.h"

namespace ui {

namespace {

template <typename T>
void TransferConsumer(GestureConsumer* current_consumer,
                      GestureConsumer* new_consumer,
                      std::map<GestureConsumer*, T>* map) {
  if (map->count(current_consumer)) {
    (*map)[new_consumer] = (*map)[current_consumer];
    map->erase(current_consumer);
  }
}

bool RemoveConsumerFromMap(GestureConsumer* consumer,
                           GestureRecognizerImpl::TouchIdToConsumerMap* map) {
  bool consumer_removed = false;
  for (GestureRecognizerImpl::TouchIdToConsumerMap::iterator i = map->begin();
       i != map->end();) {
    if (i->second == consumer) {
      map->erase(i++);
      consumer_removed = true;
    } else {
      ++i;
    }
  }
  return consumer_removed;
}

void TransferTouchIdToConsumerMap(
    GestureConsumer* old_consumer,
    GestureConsumer* new_consumer,
    GestureRecognizerImpl::TouchIdToConsumerMap* map) {
  for (GestureRecognizerImpl::TouchIdToConsumerMap::iterator i = map->begin();
       i != map->end(); ++i) {
    if (i->second == old_consumer)
      i->second = new_consumer;
  }
}

GestureProviderAura* CreateGestureProvider(GestureProviderAuraClient* client) {
  return new GestureProviderAura(client);
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// GestureRecognizerImpl, public:

GestureRecognizerImpl::GestureRecognizerImpl() {
  // Default to using the unified gesture detector.
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  const std::string unified_gd_enabled_switch =
      command_line.HasSwitch(switches::kUnifiedGestureDetector) ?
      command_line.GetSwitchValueASCII(switches::kUnifiedGestureDetector) :
      switches::kUnifiedGestureDetectorAuto;

  const bool kUseUnifiedGestureDetectorByDefault = true;
  if (unified_gd_enabled_switch.empty() ||
      unified_gd_enabled_switch == switches::kUnifiedGestureDetectorEnabled) {
    use_unified_gesture_detector_ = true;
  } else if (unified_gd_enabled_switch ==
                 switches::kUnifiedGestureDetectorDisabled) {
    use_unified_gesture_detector_ = false;
  } else if (unified_gd_enabled_switch ==
             switches::kUnifiedGestureDetectorAuto) {
    use_unified_gesture_detector_ = kUseUnifiedGestureDetectorByDefault;
  } else {
    LOG(ERROR) << "Invalid --unified-gesture-detector option: "
               << unified_gd_enabled_switch;
    use_unified_gesture_detector_ = false;
  }
}

GestureRecognizerImpl::~GestureRecognizerImpl() {
  STLDeleteValues(&consumer_sequence_);
  STLDeleteValues(&consumer_gesture_provider_);
}

// Checks if this finger is already down, if so, returns the current target.
// Otherwise, returns NULL.
GestureConsumer* GestureRecognizerImpl::GetTouchLockedTarget(
    const TouchEvent& event) {
  return touch_id_target_[event.touch_id()];
}

GestureConsumer* GestureRecognizerImpl::GetTargetForGestureEvent(
    const GestureEvent& event) {
  GestureConsumer* target = NULL;
  int touch_id = event.GetLowestTouchId();
  target = touch_id_target_for_gestures_[touch_id];
  return target;
}

GestureConsumer* GestureRecognizerImpl::GetTargetForLocation(
    const gfx::PointF& location, int source_device_id) {
  const int max_distance =
      GestureConfiguration::max_separation_for_gesture_touches_in_pixels();

  if (!use_unified_gesture_detector_) {
    const GesturePoint* closest_point = NULL;
    int64 closest_distance_squared = 0;
    std::map<GestureConsumer*, GestureSequence*>::iterator i;
    for (i = consumer_sequence_.begin(); i != consumer_sequence_.end(); ++i) {
      const GesturePoint* points = i->second->points();
      for (int j = 0; j < GestureSequence::kMaxGesturePoints; ++j) {
        if (!points[j].in_use() ||
            source_device_id != points[j].source_device_id()) {
          continue;
        }
        gfx::Vector2dF delta = points[j].last_touch_position() - location;
        // Relative distance is all we need here, so LengthSquared() is
        // appropriate, and cheaper than Length().
        int64 distance_squared = delta.LengthSquared();
        if (!closest_point || distance_squared < closest_distance_squared) {
          closest_point = &points[j];
          closest_distance_squared = distance_squared;
        }
      }
    }

    if (closest_distance_squared < max_distance * max_distance && closest_point)
      return touch_id_target_[closest_point->touch_id()];
    else
      return NULL;
  } else {
    gfx::PointF closest_point;
    int closest_touch_id;
    float closest_distance_squared = std::numeric_limits<float>::infinity();

    std::map<GestureConsumer*, GestureProviderAura*>::iterator i;
    for (i = consumer_gesture_provider_.begin();
         i != consumer_gesture_provider_.end();
         ++i) {
      const MotionEventAura& pointer_state = i->second->pointer_state();
      for (size_t j = 0; j < pointer_state.GetPointerCount(); ++j) {
        if (source_device_id != pointer_state.GetSourceDeviceId(j))
          continue;
        gfx::PointF point(pointer_state.GetX(j), pointer_state.GetY(j));
        // Relative distance is all we need here, so LengthSquared() is
        // appropriate, and cheaper than Length().
        float distance_squared = (point - location).LengthSquared();
        if (distance_squared < closest_distance_squared) {
          closest_point = point;
          closest_touch_id = pointer_state.GetPointerId(j);
          closest_distance_squared = distance_squared;
        }
      }
    }

    if (closest_distance_squared < max_distance * max_distance)
      return touch_id_target_[closest_touch_id];
    else
      return NULL;
  }
}

void GestureRecognizerImpl::TransferEventsTo(GestureConsumer* current_consumer,
                                             GestureConsumer* new_consumer) {
  // Send cancel to all those save |new_consumer| and |current_consumer|.
  // Don't send a cancel to |current_consumer|, unless |new_consumer| is NULL.
  // Dispatching a touch-cancel event can end up altering |touch_id_target_|
  // (e.g. when the target of the event is destroyed, causing it to be removed
  // from |touch_id_target_| in |CleanupStateForConsumer()|). So create a list
  // of the touch-ids that need to be cancelled, and dispatch the cancel events
  // for them at the end.
  std::vector<std::pair<int, GestureConsumer*> > ids;
  for (TouchIdToConsumerMap::iterator i = touch_id_target_.begin();
       i != touch_id_target_.end(); ++i) {
    if (i->second && i->second != new_consumer &&
        (i->second != current_consumer || new_consumer == NULL) &&
        i->second) {
      ids.push_back(std::make_pair(i->first, i->second));
    }
  }

  CancelTouches(&ids);

  // Transfer events from |current_consumer| to |new_consumer|.
  if (current_consumer && new_consumer) {
    TransferTouchIdToConsumerMap(current_consumer, new_consumer,
                                 &touch_id_target_);
    TransferTouchIdToConsumerMap(current_consumer, new_consumer,
                                 &touch_id_target_for_gestures_);
    if (!use_unified_gesture_detector_)
      TransferConsumer(current_consumer, new_consumer, &consumer_sequence_);
    else
      TransferConsumer(
          current_consumer, new_consumer, &consumer_gesture_provider_);
  }
}

bool GestureRecognizerImpl::GetLastTouchPointForTarget(
    GestureConsumer* consumer,
    gfx::PointF* point) {
  if (!use_unified_gesture_detector_) {
    if (consumer_sequence_.count(consumer) == 0)
      return false;
    *point = consumer_sequence_[consumer]->last_touch_location();
    return true;
  } else {
    if (consumer_gesture_provider_.count(consumer) == 0)
      return false;
    const MotionEvent& pointer_state =
        consumer_gesture_provider_[consumer]->pointer_state();
    *point = gfx::PointF(pointer_state.GetX(), pointer_state.GetY());
    return true;
  }
}

bool GestureRecognizerImpl::CancelActiveTouches(GestureConsumer* consumer) {
  std::vector<std::pair<int, GestureConsumer*> > ids;
  for (TouchIdToConsumerMap::const_iterator i = touch_id_target_.begin();
       i != touch_id_target_.end(); ++i) {
    if (i->second == consumer)
      ids.push_back(std::make_pair(i->first, i->second));
  }
  bool cancelled_touch = !ids.empty();
  CancelTouches(&ids);
  return cancelled_touch;
}

////////////////////////////////////////////////////////////////////////////////
// GestureRecognizerImpl, protected:

GestureSequence* GestureRecognizerImpl::CreateSequence(
    GestureSequenceDelegate* delegate) {
  return new GestureSequence(delegate);
}

////////////////////////////////////////////////////////////////////////////////
// GestureRecognizerImpl, private:

GestureSequence* GestureRecognizerImpl::GetGestureSequenceForConsumer(
    GestureConsumer* consumer) {
  GestureSequence* gesture_sequence = consumer_sequence_[consumer];
  if (!gesture_sequence) {
    gesture_sequence = CreateSequence(this);
    consumer_sequence_[consumer] = gesture_sequence;
  }
  return gesture_sequence;
}

GestureProviderAura* GestureRecognizerImpl::GetGestureProviderForConsumer(
    GestureConsumer* consumer) {
  GestureProviderAura* gesture_provider = consumer_gesture_provider_[consumer];
  if (!gesture_provider) {
    gesture_provider = CreateGestureProvider(this);
    consumer_gesture_provider_[consumer] = gesture_provider;
  }
  return gesture_provider;
}

void GestureRecognizerImpl::SetupTargets(const TouchEvent& event,
                                         GestureConsumer* target) {
  if (event.type() == ui::ET_TOUCH_RELEASED ||
      event.type() == ui::ET_TOUCH_CANCELLED) {
    touch_id_target_.erase(event.touch_id());
  } else if (event.type() == ui::ET_TOUCH_PRESSED) {
    touch_id_target_[event.touch_id()] = target;
    if (target)
      touch_id_target_for_gestures_[event.touch_id()] = target;
  }
}

void GestureRecognizerImpl::CancelTouches(
    std::vector<std::pair<int, GestureConsumer*> >* touches) {
  while (!touches->empty()) {
    int touch_id = touches->begin()->first;
    GestureConsumer* target = touches->begin()->second;
    TouchEvent touch_event(ui::ET_TOUCH_CANCELLED, gfx::PointF(0, 0),
                           ui::EF_IS_SYNTHESIZED, touch_id,
                           ui::EventTimeForNow(), 0.0f, 0.0f, 0.0f, 0.0f);
    GestureEventHelper* helper = FindDispatchHelperForConsumer(target);
    if (helper)
      helper->DispatchCancelTouchEvent(&touch_event);
    touches->erase(touches->begin());
  }
}

void GestureRecognizerImpl::DispatchGestureEvent(GestureEvent* event) {
  GestureConsumer* consumer = GetTargetForGestureEvent(*event);
  if (consumer) {
    GestureEventHelper* helper = FindDispatchHelperForConsumer(consumer);
    if (helper)
      helper->DispatchGestureEvent(event);
  }
}

ScopedVector<GestureEvent>* GestureRecognizerImpl::ProcessTouchEventForGesture(
    const TouchEvent& event,
    ui::EventResult result,
    GestureConsumer* target) {
  SetupTargets(event, target);

  if (!use_unified_gesture_detector_) {
    GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target);
    return gesture_sequence->ProcessTouchEventForGesture(event, result);
  } else {
    GestureProviderAura* gesture_provider =
        GetGestureProviderForConsumer(target);
    // TODO(tdresser) - detect gestures eagerly.
    if (!(result & ER_CONSUMED)) {
      if (gesture_provider->OnTouchEvent(event)) {
        gesture_provider->OnTouchEventAck(result != ER_UNHANDLED);
        return gesture_provider->GetAndResetPendingGestures();
      }
    }
    return NULL;
  }
}

bool GestureRecognizerImpl::CleanupStateForConsumer(
    GestureConsumer* consumer) {
  bool state_cleaned_up = false;

  if (!use_unified_gesture_detector_) {
    if (consumer_sequence_.count(consumer)) {
      state_cleaned_up = true;
      delete consumer_sequence_[consumer];
      consumer_sequence_.erase(consumer);
    }
  } else {
    if (consumer_gesture_provider_.count(consumer)) {
      state_cleaned_up = true;
      delete consumer_gesture_provider_[consumer];
      consumer_gesture_provider_.erase(consumer);
    }
  }

  state_cleaned_up |= RemoveConsumerFromMap(consumer, &touch_id_target_);
  state_cleaned_up |=
      RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_);
  return state_cleaned_up;
}

void GestureRecognizerImpl::AddGestureEventHelper(GestureEventHelper* helper) {
  helpers_.push_back(helper);
}

void GestureRecognizerImpl::RemoveGestureEventHelper(
    GestureEventHelper* helper) {
  std::vector<GestureEventHelper*>::iterator it = std::find(helpers_.begin(),
      helpers_.end(), helper);
  if (it != helpers_.end())
    helpers_.erase(it);
}

void GestureRecognizerImpl::DispatchPostponedGestureEvent(GestureEvent* event) {
  DispatchGestureEvent(event);
}

void GestureRecognizerImpl::OnGestureEvent(GestureEvent* event) {
  DispatchGestureEvent(event);
}

GestureEventHelper* GestureRecognizerImpl::FindDispatchHelperForConsumer(
    GestureConsumer* consumer) {
  std::vector<GestureEventHelper*>::iterator it;
  for (it = helpers_.begin(); it != helpers_.end(); ++it) {
    if ((*it)->CanDispatchToConsumer(consumer))
      return (*it);
  }
  return NULL;
}

// GestureRecognizer, static
GestureRecognizer* GestureRecognizer::Create() {
  return new GestureRecognizerImpl();
}

static GestureRecognizerImpl* g_gesture_recognizer_instance = NULL;

// GestureRecognizer, static
GestureRecognizer* GestureRecognizer::Get() {
  if (!g_gesture_recognizer_instance)
    g_gesture_recognizer_instance = new GestureRecognizerImpl();
  return g_gesture_recognizer_instance;
}

// GestureRecognizer, static
void GestureRecognizer::Reset() {
  delete g_gesture_recognizer_instance;
  g_gesture_recognizer_instance = NULL;
}

void SetGestureRecognizerForTesting(GestureRecognizer* gesture_recognizer) {
  // Transfer helpers to the new GR.
  std::vector<GestureEventHelper*>& helpers =
      g_gesture_recognizer_instance->helpers();
  std::vector<GestureEventHelper*>::iterator it;
  for (it = helpers.begin(); it != helpers.end(); ++it)
    gesture_recognizer->AddGestureEventHelper(*it);

  helpers.clear();
  g_gesture_recognizer_instance =
      static_cast<GestureRecognizerImpl*>(gesture_recognizer);
}

}  // namespace ui
<commit_msg>Disable unified gesture detector<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/events/gestures/gesture_recognizer_impl.h"

#include <limits>

#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_switches.h"
#include "ui/events/event_utils.h"
#include "ui/events/gestures/gesture_configuration.h"
#include "ui/events/gestures/gesture_sequence.h"
#include "ui/events/gestures/gesture_types.h"

namespace ui {

namespace {

template <typename T>
void TransferConsumer(GestureConsumer* current_consumer,
                      GestureConsumer* new_consumer,
                      std::map<GestureConsumer*, T>* map) {
  if (map->count(current_consumer)) {
    (*map)[new_consumer] = (*map)[current_consumer];
    map->erase(current_consumer);
  }
}

bool RemoveConsumerFromMap(GestureConsumer* consumer,
                           GestureRecognizerImpl::TouchIdToConsumerMap* map) {
  bool consumer_removed = false;
  for (GestureRecognizerImpl::TouchIdToConsumerMap::iterator i = map->begin();
       i != map->end();) {
    if (i->second == consumer) {
      map->erase(i++);
      consumer_removed = true;
    } else {
      ++i;
    }
  }
  return consumer_removed;
}

void TransferTouchIdToConsumerMap(
    GestureConsumer* old_consumer,
    GestureConsumer* new_consumer,
    GestureRecognizerImpl::TouchIdToConsumerMap* map) {
  for (GestureRecognizerImpl::TouchIdToConsumerMap::iterator i = map->begin();
       i != map->end(); ++i) {
    if (i->second == old_consumer)
      i->second = new_consumer;
  }
}

GestureProviderAura* CreateGestureProvider(GestureProviderAuraClient* client) {
  return new GestureProviderAura(client);
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// GestureRecognizerImpl, public:

GestureRecognizerImpl::GestureRecognizerImpl() {
  // Default to not using the unified gesture detector.
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  const std::string unified_gd_enabled_switch =
      command_line.HasSwitch(switches::kUnifiedGestureDetector) ?
      command_line.GetSwitchValueASCII(switches::kUnifiedGestureDetector) :
      switches::kUnifiedGestureDetectorAuto;

  const bool kUseUnifiedGestureDetectorByDefault = false;
  if (unified_gd_enabled_switch.empty() ||
      unified_gd_enabled_switch == switches::kUnifiedGestureDetectorEnabled) {
    use_unified_gesture_detector_ = true;
  } else if (unified_gd_enabled_switch ==
                 switches::kUnifiedGestureDetectorDisabled) {
    use_unified_gesture_detector_ = false;
  } else if (unified_gd_enabled_switch ==
             switches::kUnifiedGestureDetectorAuto) {
    use_unified_gesture_detector_ = kUseUnifiedGestureDetectorByDefault;
  } else {
    LOG(ERROR) << "Invalid --unified-gesture-detector option: "
               << unified_gd_enabled_switch;
    use_unified_gesture_detector_ = false;
  }
}

GestureRecognizerImpl::~GestureRecognizerImpl() {
  STLDeleteValues(&consumer_sequence_);
  STLDeleteValues(&consumer_gesture_provider_);
}

// Checks if this finger is already down, if so, returns the current target.
// Otherwise, returns NULL.
GestureConsumer* GestureRecognizerImpl::GetTouchLockedTarget(
    const TouchEvent& event) {
  return touch_id_target_[event.touch_id()];
}

GestureConsumer* GestureRecognizerImpl::GetTargetForGestureEvent(
    const GestureEvent& event) {
  GestureConsumer* target = NULL;
  int touch_id = event.GetLowestTouchId();
  target = touch_id_target_for_gestures_[touch_id];
  return target;
}

GestureConsumer* GestureRecognizerImpl::GetTargetForLocation(
    const gfx::PointF& location, int source_device_id) {
  const int max_distance =
      GestureConfiguration::max_separation_for_gesture_touches_in_pixels();

  if (!use_unified_gesture_detector_) {
    const GesturePoint* closest_point = NULL;
    int64 closest_distance_squared = 0;
    std::map<GestureConsumer*, GestureSequence*>::iterator i;
    for (i = consumer_sequence_.begin(); i != consumer_sequence_.end(); ++i) {
      const GesturePoint* points = i->second->points();
      for (int j = 0; j < GestureSequence::kMaxGesturePoints; ++j) {
        if (!points[j].in_use() ||
            source_device_id != points[j].source_device_id()) {
          continue;
        }
        gfx::Vector2dF delta = points[j].last_touch_position() - location;
        // Relative distance is all we need here, so LengthSquared() is
        // appropriate, and cheaper than Length().
        int64 distance_squared = delta.LengthSquared();
        if (!closest_point || distance_squared < closest_distance_squared) {
          closest_point = &points[j];
          closest_distance_squared = distance_squared;
        }
      }
    }

    if (closest_distance_squared < max_distance * max_distance && closest_point)
      return touch_id_target_[closest_point->touch_id()];
    else
      return NULL;
  } else {
    gfx::PointF closest_point;
    int closest_touch_id;
    float closest_distance_squared = std::numeric_limits<float>::infinity();

    std::map<GestureConsumer*, GestureProviderAura*>::iterator i;
    for (i = consumer_gesture_provider_.begin();
         i != consumer_gesture_provider_.end();
         ++i) {
      const MotionEventAura& pointer_state = i->second->pointer_state();
      for (size_t j = 0; j < pointer_state.GetPointerCount(); ++j) {
        if (source_device_id != pointer_state.GetSourceDeviceId(j))
          continue;
        gfx::PointF point(pointer_state.GetX(j), pointer_state.GetY(j));
        // Relative distance is all we need here, so LengthSquared() is
        // appropriate, and cheaper than Length().
        float distance_squared = (point - location).LengthSquared();
        if (distance_squared < closest_distance_squared) {
          closest_point = point;
          closest_touch_id = pointer_state.GetPointerId(j);
          closest_distance_squared = distance_squared;
        }
      }
    }

    if (closest_distance_squared < max_distance * max_distance)
      return touch_id_target_[closest_touch_id];
    else
      return NULL;
  }
}

void GestureRecognizerImpl::TransferEventsTo(GestureConsumer* current_consumer,
                                             GestureConsumer* new_consumer) {
  // Send cancel to all those save |new_consumer| and |current_consumer|.
  // Don't send a cancel to |current_consumer|, unless |new_consumer| is NULL.
  // Dispatching a touch-cancel event can end up altering |touch_id_target_|
  // (e.g. when the target of the event is destroyed, causing it to be removed
  // from |touch_id_target_| in |CleanupStateForConsumer()|). So create a list
  // of the touch-ids that need to be cancelled, and dispatch the cancel events
  // for them at the end.
  std::vector<std::pair<int, GestureConsumer*> > ids;
  for (TouchIdToConsumerMap::iterator i = touch_id_target_.begin();
       i != touch_id_target_.end(); ++i) {
    if (i->second && i->second != new_consumer &&
        (i->second != current_consumer || new_consumer == NULL) &&
        i->second) {
      ids.push_back(std::make_pair(i->first, i->second));
    }
  }

  CancelTouches(&ids);

  // Transfer events from |current_consumer| to |new_consumer|.
  if (current_consumer && new_consumer) {
    TransferTouchIdToConsumerMap(current_consumer, new_consumer,
                                 &touch_id_target_);
    TransferTouchIdToConsumerMap(current_consumer, new_consumer,
                                 &touch_id_target_for_gestures_);
    if (!use_unified_gesture_detector_)
      TransferConsumer(current_consumer, new_consumer, &consumer_sequence_);
    else
      TransferConsumer(
          current_consumer, new_consumer, &consumer_gesture_provider_);
  }
}

bool GestureRecognizerImpl::GetLastTouchPointForTarget(
    GestureConsumer* consumer,
    gfx::PointF* point) {
  if (!use_unified_gesture_detector_) {
    if (consumer_sequence_.count(consumer) == 0)
      return false;
    *point = consumer_sequence_[consumer]->last_touch_location();
    return true;
  } else {
    if (consumer_gesture_provider_.count(consumer) == 0)
      return false;
    const MotionEvent& pointer_state =
        consumer_gesture_provider_[consumer]->pointer_state();
    *point = gfx::PointF(pointer_state.GetX(), pointer_state.GetY());
    return true;
  }
}

bool GestureRecognizerImpl::CancelActiveTouches(GestureConsumer* consumer) {
  std::vector<std::pair<int, GestureConsumer*> > ids;
  for (TouchIdToConsumerMap::const_iterator i = touch_id_target_.begin();
       i != touch_id_target_.end(); ++i) {
    if (i->second == consumer)
      ids.push_back(std::make_pair(i->first, i->second));
  }
  bool cancelled_touch = !ids.empty();
  CancelTouches(&ids);
  return cancelled_touch;
}

////////////////////////////////////////////////////////////////////////////////
// GestureRecognizerImpl, protected:

GestureSequence* GestureRecognizerImpl::CreateSequence(
    GestureSequenceDelegate* delegate) {
  return new GestureSequence(delegate);
}

////////////////////////////////////////////////////////////////////////////////
// GestureRecognizerImpl, private:

GestureSequence* GestureRecognizerImpl::GetGestureSequenceForConsumer(
    GestureConsumer* consumer) {
  GestureSequence* gesture_sequence = consumer_sequence_[consumer];
  if (!gesture_sequence) {
    gesture_sequence = CreateSequence(this);
    consumer_sequence_[consumer] = gesture_sequence;
  }
  return gesture_sequence;
}

GestureProviderAura* GestureRecognizerImpl::GetGestureProviderForConsumer(
    GestureConsumer* consumer) {
  GestureProviderAura* gesture_provider = consumer_gesture_provider_[consumer];
  if (!gesture_provider) {
    gesture_provider = CreateGestureProvider(this);
    consumer_gesture_provider_[consumer] = gesture_provider;
  }
  return gesture_provider;
}

void GestureRecognizerImpl::SetupTargets(const TouchEvent& event,
                                         GestureConsumer* target) {
  if (event.type() == ui::ET_TOUCH_RELEASED ||
      event.type() == ui::ET_TOUCH_CANCELLED) {
    touch_id_target_.erase(event.touch_id());
  } else if (event.type() == ui::ET_TOUCH_PRESSED) {
    touch_id_target_[event.touch_id()] = target;
    if (target)
      touch_id_target_for_gestures_[event.touch_id()] = target;
  }
}

void GestureRecognizerImpl::CancelTouches(
    std::vector<std::pair<int, GestureConsumer*> >* touches) {
  while (!touches->empty()) {
    int touch_id = touches->begin()->first;
    GestureConsumer* target = touches->begin()->second;
    TouchEvent touch_event(ui::ET_TOUCH_CANCELLED, gfx::PointF(0, 0),
                           ui::EF_IS_SYNTHESIZED, touch_id,
                           ui::EventTimeForNow(), 0.0f, 0.0f, 0.0f, 0.0f);
    GestureEventHelper* helper = FindDispatchHelperForConsumer(target);
    if (helper)
      helper->DispatchCancelTouchEvent(&touch_event);
    touches->erase(touches->begin());
  }
}

void GestureRecognizerImpl::DispatchGestureEvent(GestureEvent* event) {
  GestureConsumer* consumer = GetTargetForGestureEvent(*event);
  if (consumer) {
    GestureEventHelper* helper = FindDispatchHelperForConsumer(consumer);
    if (helper)
      helper->DispatchGestureEvent(event);
  }
}

ScopedVector<GestureEvent>* GestureRecognizerImpl::ProcessTouchEventForGesture(
    const TouchEvent& event,
    ui::EventResult result,
    GestureConsumer* target) {
  SetupTargets(event, target);

  if (!use_unified_gesture_detector_) {
    GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target);
    return gesture_sequence->ProcessTouchEventForGesture(event, result);
  } else {
    GestureProviderAura* gesture_provider =
        GetGestureProviderForConsumer(target);
    // TODO(tdresser) - detect gestures eagerly.
    if (!(result & ER_CONSUMED)) {
      if (gesture_provider->OnTouchEvent(event)) {
        gesture_provider->OnTouchEventAck(result != ER_UNHANDLED);
        return gesture_provider->GetAndResetPendingGestures();
      }
    }
    return NULL;
  }
}

bool GestureRecognizerImpl::CleanupStateForConsumer(
    GestureConsumer* consumer) {
  bool state_cleaned_up = false;

  if (!use_unified_gesture_detector_) {
    if (consumer_sequence_.count(consumer)) {
      state_cleaned_up = true;
      delete consumer_sequence_[consumer];
      consumer_sequence_.erase(consumer);
    }
  } else {
    if (consumer_gesture_provider_.count(consumer)) {
      state_cleaned_up = true;
      delete consumer_gesture_provider_[consumer];
      consumer_gesture_provider_.erase(consumer);
    }
  }

  state_cleaned_up |= RemoveConsumerFromMap(consumer, &touch_id_target_);
  state_cleaned_up |=
      RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_);
  return state_cleaned_up;
}

void GestureRecognizerImpl::AddGestureEventHelper(GestureEventHelper* helper) {
  helpers_.push_back(helper);
}

void GestureRecognizerImpl::RemoveGestureEventHelper(
    GestureEventHelper* helper) {
  std::vector<GestureEventHelper*>::iterator it = std::find(helpers_.begin(),
      helpers_.end(), helper);
  if (it != helpers_.end())
    helpers_.erase(it);
}

void GestureRecognizerImpl::DispatchPostponedGestureEvent(GestureEvent* event) {
  DispatchGestureEvent(event);
}

void GestureRecognizerImpl::OnGestureEvent(GestureEvent* event) {
  DispatchGestureEvent(event);
}

GestureEventHelper* GestureRecognizerImpl::FindDispatchHelperForConsumer(
    GestureConsumer* consumer) {
  std::vector<GestureEventHelper*>::iterator it;
  for (it = helpers_.begin(); it != helpers_.end(); ++it) {
    if ((*it)->CanDispatchToConsumer(consumer))
      return (*it);
  }
  return NULL;
}

// GestureRecognizer, static
GestureRecognizer* GestureRecognizer::Create() {
  return new GestureRecognizerImpl();
}

static GestureRecognizerImpl* g_gesture_recognizer_instance = NULL;

// GestureRecognizer, static
GestureRecognizer* GestureRecognizer::Get() {
  if (!g_gesture_recognizer_instance)
    g_gesture_recognizer_instance = new GestureRecognizerImpl();
  return g_gesture_recognizer_instance;
}

// GestureRecognizer, static
void GestureRecognizer::Reset() {
  delete g_gesture_recognizer_instance;
  g_gesture_recognizer_instance = NULL;
}

void SetGestureRecognizerForTesting(GestureRecognizer* gesture_recognizer) {
  // Transfer helpers to the new GR.
  std::vector<GestureEventHelper*>& helpers =
      g_gesture_recognizer_instance->helpers();
  std::vector<GestureEventHelper*>::iterator it;
  for (it = helpers.begin(); it != helpers.end(); ++it)
    gesture_recognizer->AddGestureEventHelper(*it);

  helpers.clear();
  g_gesture_recognizer_instance =
      static_cast<GestureRecognizerImpl*>(gesture_recognizer);
}

}  // namespace ui
<|endoftext|>


<commit_before>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <iostream>
#include <stdexcept>

#include "UsbHandler.h"
#include "LibusbDevice.h"

#include "logging.h"

#include <cstring>

namespace tcam
{

UsbHandler& UsbHandler::get_instance ()
{
    static UsbHandler instance;

    return instance;
}

UsbHandler::UsbHandler ():
    session(new UsbSession())
{}

UsbHandler::~UsbHandler()
{}

struct libusb_device_handle* UsbHandler::open_device (const std::string& serial)
{
    struct libusb_device_handle* ret = nullptr;

    libusb_device** devs;

    int cnt = libusb_get_device_list(this->session->get_session(), &devs);

    if (cnt < 0)
    {
        throw std::runtime_error("Unable to retrieve device list. " + std::to_string(cnt));
    }

    for (ssize_t i = 0; i < cnt; i++)
    {
        libusb_device_descriptor desc;
        int r = libusb_get_device_descriptor(devs[i], &desc);
        if (r < 0)
        {
            throw std::runtime_error("Unable to retrieve device descriptor. " + std::to_string(cnt));
        }

        // ignore all devices that are not from TIS or otherwise needed
        if (desc.idVendor != 0x199e)
            continue;

        if (desc.idProduct != 0x8209)
            continue;

        r = libusb_open(devs[i], &ret);

        if (r < 0)
        {
            tcam_log(TCAM_LOG_ERROR, "Unable to open device.");
            continue;
        }

        char tmp_str[sizeof(tcam_device_info::serial_number)];

        libusb_get_string_descriptor_ascii(ret, desc.iSerialNumber,
                                           (unsigned char*)tmp_str,
                                           sizeof(tcam_device_info::serial_number));
        if (serial.compare(tmp_str) == 0)
        {

            break;
        }

        libusb_close(ret);

    }

    libusb_free_device_list(devs, 1);

    return ret;
}

std::vector<DeviceInfo> UsbHandler::get_device_list ()
{
    libusb_device** devs;

    int cnt = libusb_get_device_list(this->session->get_session(), &devs);

    if (cnt < 0)
    {
        throw std::runtime_error("Unable to retrieve device list. " + std::to_string(cnt));
    }

    std::vector<DeviceInfo> ret;
    ret.reserve(5);

    for (ssize_t i = 0; i < cnt; i++)
    {
        libusb_device_descriptor desc;
        int r = libusb_get_device_descriptor(devs[i], &desc);
        if (r < 0)
        {
            throw std::runtime_error("Unable to retrieve device descriptor. " + std::to_string(cnt));
        }

        // ignore all devices that are not from TIS or otherwise needed
        if (desc.idVendor != 0x199e)
            continue;

        if (desc.idProduct != 0x8209)
            continue;

        tcam_device_info d = { };

        d.type = TCAM_DEVICE_TYPE_LIBUSB;

        // d.idVendor = desc.idVendor;
        // d.idProduct = desc.idProduct;

        // strcpy(d.name, "AFU050");
        // strcpy(d.serial_number, "47614135");
        // strcpy(d.additional_identifier, "9209");

        libusb_device_handle* dh;
        r = libusb_open(devs[i], &dh);

        if (r < 0)
        {
            tcam_log(TCAM_LOG_ERROR, "Unable to open device.");
            continue;
        }

        libusb_get_string_descriptor_ascii(dh, desc.iProduct, (unsigned char*)d.name, sizeof(d.name));

        // libusb_get_string_descriptor_ascii(dh, desc.iManufacturer, (unsigned char*)d.manufacturer, sizeof(d.manufacturer));
        // int lib_ret = libusb_get_port_numbers(dh, (uint8_t*)d.identifier, sizeof(d.identifier))

        libusb_get_string_descriptor_ascii(dh, desc.idProduct, (unsigned char*)d.additional_identifier, sizeof(d.additional_identifier));
        libusb_get_string_descriptor_ascii(dh, desc.iSerialNumber, (unsigned char*)d.serial_number, sizeof(d.serial_number));

        libusb_close(dh);
        ret.push_back(DeviceInfo(d));
    }

    libusb_free_device_list(devs, 1);

    return ret;
}

// std::shared_ptr<UsbCamera> UsbHandler::open_camera (std::string serial_number)
// {
//     auto list = get_device_list();
//     device_info d;

//     for (auto& dev : list)
//     {
//         // std::cout << "Comparing |" << dev.serial << "|" << (unsigned char*)serial_number.c_str() << "|" << std::endl;
//         if (serial_number.compare(dev.serial) == 0)
//         {
//              // std::cout << "dev.serial " << dev.serial << ";serial " << serial_number << std::endl;
//             d = dev;
//             break;
//         }
//     }

//     camera_type t = find_camera_type(d.idVendor, d.idProduct);

//     switch(t.camera_type)
//     {
//         case USB33:
//             return std::make_shared<Usb33Camera>(this->session, d);
//         case USB3:
//             return std::make_shared<Usb3Camera>(this->session, d);
//         case USB2:
//             return std::make_shared<Usb2Camera>(this->session, d);
//         case UNKNOWN:
//         default:
//             return nullptr;
//     }
// }

std::shared_ptr<UsbSession> UsbHandler::get_session ()
{
    return this->session;
}

}; /* namespace tis */
<commit_msg>Add afu420 device listing and libusb_device_handle opening<commit_after>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <iostream>
#include <stdexcept>

#include "UsbHandler.h"
#include "LibusbDevice.h"

#include "logging.h"

#include <cstring>

namespace tcam
{

UsbHandler& UsbHandler::get_instance ()
{
    static UsbHandler instance;

    return instance;
}

UsbHandler::UsbHandler ():
    session(new UsbSession())
{}

UsbHandler::~UsbHandler()
{}

struct libusb_device_handle* UsbHandler::open_device (const std::string& serial)
{
    struct libusb_device_handle* ret = nullptr;

    libusb_device** devs;

    int cnt = libusb_get_device_list(this->session->get_session(), &devs);

    if (cnt < 0)
    {
        throw std::runtime_error("Unable to retrieve device list. " + std::to_string(cnt));
    }

    for (ssize_t i = 0; i < cnt; i++)
    {
        libusb_device_descriptor desc;
        int r = libusb_get_device_descriptor(devs[i], &desc);
        if (r < 0)
        {
            throw std::runtime_error("Unable to retrieve device descriptor. " + std::to_string(cnt));
        }

        // ignore all devices that are not from TIS or otherwise needed
        if (desc.idVendor != 0x199e)
            continue;

        if (desc.idProduct != 0x8209 && desc.idProduct != 0x0804)
            continue;

        r = libusb_open(devs[i], &ret);

        if (r < 0)
        {
            tcam_log(TCAM_LOG_ERROR, "Unable to open device.");
            continue;
        }

        char tmp_str[sizeof(tcam_device_info::serial_number)];

        libusb_get_string_descriptor_ascii(ret, desc.iSerialNumber,
                                           (unsigned char*)tmp_str,
                                           sizeof(tcam_device_info::serial_number));
        if (serial.compare(tmp_str) == 0)
        {

            break;
        }

        libusb_close(ret);

    }

    libusb_free_device_list(devs, 1);

    return ret;
}

std::vector<DeviceInfo> UsbHandler::get_device_list ()
{
    libusb_device** devs;

    int cnt = libusb_get_device_list(this->session->get_session(), &devs);

    if (cnt < 0)
    {
        throw std::runtime_error("Unable to retrieve device list. " + std::to_string(cnt));
    }

    std::vector<DeviceInfo> ret;
    ret.reserve(5);

    for (ssize_t i = 0; i < cnt; i++)
    {
        libusb_device_descriptor desc;
        int r = libusb_get_device_descriptor(devs[i], &desc);
        if (r < 0)
        {
            throw std::runtime_error("Unable to retrieve device descriptor. " + std::to_string(cnt));
        }

        // ignore all devices that are not from TIS or otherwise needed
        if (desc.idVendor != 0x199e)
            continue;

        if (desc.idProduct != 0x8209 && desc.idProduct != 0x0804)
            continue;

        tcam_device_info d = { };

        d.type = TCAM_DEVICE_TYPE_LIBUSB;

        // d.idVendor = desc.idVendor;
        // d.idProduct = desc.idProduct;

        // strcpy(d.name, "AFU050");
        // strcpy(d.serial_number, "47614135");
        // strcpy(d.additional_identifier, "9209");

        libusb_device_handle* dh;
        r = libusb_open(devs[i], &dh);

        if (r < 0)
        {
            tcam_log(TCAM_LOG_ERROR, "Unable to open device.");
            continue;
        }

        libusb_get_string_descriptor_ascii(dh, desc.iProduct, (unsigned char*)d.name, sizeof(d.name));

        // libusb_get_string_descriptor_ascii(dh, desc.iManufacturer, (unsigned char*)d.manufacturer, sizeof(d.manufacturer));
        // int lib_ret = libusb_get_port_numbers(dh, (uint8_t*)d.identifier, sizeof(d.identifier))

        libusb_get_string_descriptor_ascii(dh, desc.idProduct, (unsigned char*)d.additional_identifier, sizeof(d.additional_identifier));
        libusb_get_string_descriptor_ascii(dh, desc.iSerialNumber, (unsigned char*)d.serial_number, sizeof(d.serial_number));

        libusb_close(dh);
        ret.push_back(DeviceInfo(d));
    }

    libusb_free_device_list(devs, 1);

    return ret;
}

// std::shared_ptr<UsbCamera> UsbHandler::open_camera (std::string serial_number)
// {
//     auto list = get_device_list();
//     device_info d;

//     for (auto& dev : list)
//     {
//         // std::cout << "Comparing |" << dev.serial << "|" << (unsigned char*)serial_number.c_str() << "|" << std::endl;
//         if (serial_number.compare(dev.serial) == 0)
//         {
//              // std::cout << "dev.serial " << dev.serial << ";serial " << serial_number << std::endl;
//             d = dev;
//             break;
//         }
//     }

//     camera_type t = find_camera_type(d.idVendor, d.idProduct);

//     switch(t.camera_type)
//     {
//         case USB33:
//             return std::make_shared<Usb33Camera>(this->session, d);
//         case USB3:
//             return std::make_shared<Usb3Camera>(this->session, d);
//         case USB2:
//             return std::make_shared<Usb2Camera>(this->session, d);
//         case UNKNOWN:
//         default:
//             return nullptr;
//     }
// }

std::shared_ptr<UsbSession> UsbHandler::get_session ()
{
    return this->session;
}

}; /* namespace tis */
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <memory.h>
#include <math.h>
#include <matio.h>
#include <atomic>
#include <iostream>
#include "analog.pb.h"
#include "analogchan.h"
#include "matStor.h"
#include "analogwriter.h"

#define u64 unsigned long long
#define i64 long long
#define u32 unsigned int

//#define _LARGEFILE_SOURCE enabled by default.
#define _FILE_OFFSET_BITS 64

using namespace std;
using namespace google::protobuf;
using namespace gtkclient;

int main(int argn, char **argc)
{

	GOOGLE_PROTOBUF_VERIFY_VERSION;

	ifstream in;

	if (argn != 3 && argn != 2) {
		printf("usage: analog2mat infile.dat outfile.mat\n");
		printf(" or just: analog2mat infile.dat\n");
		exit(0);
	}

	// in file
	in.open(argc[1]);
	if (!in.good()) {
		fprintf(stderr,"Could not open %s\n", argc[1]);
		exit(0);
	}

	// out file
	int nn = strlen(argc[1]);
	if (nn < 5 || nn > 511) {
		printf(" infile not .bin?\n");
		exit(0);
	}
	char s[512];
	if (argn == 2) {
		strncpy(s, argc[1], 512);
		s[nn-3] = 'm';
		s[nn-2] = 'a';
		s[nn-1] = 't';
	} else {
		strncpy(s, argc[2], 512);
	}
	MatStor ms(s);

	unsigned long packets=0;
	map<unsigned int,AnalogChan *> analchans;

	while (!in.eof()) {

		// read magic
		unsigned int magic;
		in.read((char *) &magic, sizeof(magic));
		if (in.eof())
			break;
		if (in.fail() || in.gcount() != sizeof (magic)) {
			fprintf(stderr,
			        "read magic failure. gcount: %ld at %d\n",
			        in.gcount(), (int) in.tellg());
			exit(0);
		}
		if (magic != ANALOG_MAGIC) {
			fprintf(stderr, "packet %ld: magic value, %X, does not match expected value, %X.\n", packets+1, magic, ANALOG_MAGIC);
			exit(0);
		}

		// read size
		unsigned int sz;
		in.read((char *) &sz, sizeof (sz));
		if (in.eof())
			exit(0);
		if (in.fail() || in.gcount() != sizeof (sz)) {
			fprintf(stderr, "read size failure. gcount: %ld at %d\n",
			        in.gcount(), (int) in.tellg());
			exit(0);
		}
		if (sz > 131072) { // hardcoded for now xxx
			fprintf(stderr, "single packet too long for buffer: %u.\n", sz);
			exit(0);
		}

		// read protobuf packet
		char buf[131072]; // xxx
		in.read(buf, sz);
		if (in.fail() || in.eof() || in.gcount() != sz) {
			fprintf(stderr, "read protobuf packet failure\n");
			exit(0);
		}

		// parse protobuf
		Analog a;
		a.Clear();
		if (!a.ParseFromArray(buf, sz)) {
			fprintf(stderr, "failed to parse protobuf packet %ld (%d bytes). aborting here.\n",
			        packets+1, sz);
			break;
		}

		unsigned int ch = a.chan();

		// try to find the analog chan in our map
		AnalogChan *ac = NULL;
		if (analchans.find(ch) == analchans.end()) {
			// not found, it is a new chan
			ac = new AnalogChan();
			if (!ac) {
				fprintf(stderr, "Out of memory\n");
				continue;
			}
			analchans[ch] = ac;
			ac->chan = ch;
		} else {
			// found, set pointer to exisiting analog chan
			ac = analchans[ch];
		}

		if (a.tick_size() != a.sample_size()) {
			fprintf(stderr, "samples and ticks dont align!\n");
			exit(0);
		}

		for (int i=0; i<a.tick_size(); i++)
			if (!ac->add_sample(a.ts(i), a.tick(i), a.sample(i)))
				fprintf(stderr, "Error adding sample for analog chan %u (packet %lu)\n", ch, packets);

		packets++;
		//printf("parsed %ld packets\n", packets);

	}
	in.close();

	ShutdownProtobufLibrary();

	printf("Parsing complete. %lu total packets from %lu analog chans.\n",
	       packets, analchans.size());

	// now write each stim chan
	map<unsigned int, AnalogChan *>::iterator it;
	for (it = analchans.begin(); it != analchans.end(); it++) {
		printf("analog ch: %d\n", (*it).second->chan);
		(*it).second->save(&ms);
	}

	ms.save();

	return 0;
}<commit_msg>change some instances to packets+1 since counting from zero doesnt make sense for this<commit_after>#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <memory.h>
#include <math.h>
#include <matio.h>
#include <atomic>
#include <iostream>
#include "analog.pb.h"
#include "analogchan.h"
#include "matStor.h"
#include "analogwriter.h"

#define u64 unsigned long long
#define i64 long long
#define u32 unsigned int

//#define _LARGEFILE_SOURCE enabled by default.
#define _FILE_OFFSET_BITS 64

using namespace std;
using namespace google::protobuf;
using namespace gtkclient;

int main(int argn, char **argc)
{

	GOOGLE_PROTOBUF_VERIFY_VERSION;

	ifstream in;

	if (argn != 3 && argn != 2) {
		printf("usage: analog2mat infile.dat outfile.mat\n");
		printf(" or just: analog2mat infile.dat\n");
		exit(0);
	}

	// in file
	in.open(argc[1]);
	if (!in.good()) {
		fprintf(stderr,"Could not open %s\n", argc[1]);
		exit(0);
	}

	// out file
	int nn = strlen(argc[1]);
	if (nn < 5 || nn > 511) {
		printf(" infile not .bin?\n");
		exit(0);
	}
	char s[512];
	if (argn == 2) {
		strncpy(s, argc[1], 512);
		s[nn-3] = 'm';
		s[nn-2] = 'a';
		s[nn-1] = 't';
	} else {
		strncpy(s, argc[2], 512);
	}
	MatStor ms(s);

	unsigned long packets=0;
	map<unsigned int,AnalogChan *> analchans;

	while (!in.eof()) {

		// read magic
		unsigned int magic;
		in.read((char *) &magic, sizeof(magic));
		if (in.eof())
			break;
		if (in.fail() || in.gcount() != sizeof (magic)) {
			fprintf(stderr,
			        "read magic failure. gcount: %ld at %d\n",
			        in.gcount(), (int) in.tellg());
			exit(0);
		}
		if (magic != ANALOG_MAGIC) {
			fprintf(stderr, "packet %ld: magic value, %X, does not match expected value, %X. aborting here.\n",
			        packets+1, magic, ANALOG_MAGIC);
			break;
		}

		// read size
		unsigned int sz;
		in.read((char *) &sz, sizeof (sz));
		if (in.eof())
			exit(0);
		if (in.fail() || in.gcount() != sizeof (sz)) {
			fprintf(stderr, "read size failure. gcount: %ld at %d\n",
			        in.gcount(), (int) in.tellg());
			exit(0);
		}
		if (sz > 131072) { // hardcoded for now xxx
			fprintf(stderr, "single packet too long for buffer: %u.\n", sz);
			exit(0);
		}

		// read protobuf packet
		// max int32 is  2,147,483,647
		// max uint32 is 4,294,967,295
		char buf[131072]; // xxx
		in.read(buf, sz);
		if (in.fail() || in.eof() || in.gcount() != sz) {
			fprintf(stderr, "read protobuf packet failure\n");
			exit(0);
		}

		// parse protobuf
		Analog a;
		a.Clear();
		if (!a.ParseFromArray(buf, sz)) {
			fprintf(stderr, "failed to parse protobuf packet %ld (%d bytes). aborting here.\n",
			        packets+1, sz);
			break;
		}

		unsigned int ch = a.chan();

		// try to find the analog chan in our map
		AnalogChan *ac = NULL;
		if (analchans.find(ch) == analchans.end()) {
			// not found, it is a new chan
			ac = new AnalogChan();
			if (!ac) {
				fprintf(stderr, "Out of memory\n");
				continue;
			}
			analchans[ch] = ac;
			ac->chan = ch;
		} else {
			// found, set pointer to exisiting analog chan
			ac = analchans[ch];
		}

		if (a.tick_size() != a.sample_size()) {
			fprintf(stderr, "samples and ticks dont align!\n");
			exit(0);
		}

		for (int i=0; i<a.tick_size(); i++)
			if (!ac->add_sample(a.ts(i), a.tick(i), a.sample(i)))
				fprintf(stderr, "Error adding sample for analog chan %u (packet %lu)\n", ch, packets+1);

		packets++;
		//printf("parsed %ld packets\n", packets);

	}
	in.close();

	ShutdownProtobufLibrary();

	printf("Parsing complete. %lu total packets from %lu analog chans.\n",
	       packets+1, analchans.size());

	// now write each stim chan
	map<unsigned int, AnalogChan *>::iterator it;
	for (it = analchans.begin(); it != analchans.end(); it++) {
		printf("analog ch: %d\n", (*it).second->chan);
		(*it).second->save(&ms);
	}

	ms.save();

	return 0;
}<|endoftext|>


<commit_before>//
//  rv-meta.cc
//

#include <cstdio>
#include <sstream>
#include <functional>
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include <deque>
#include <map>
#include <set>

#include "util.h"
#include "cmdline.h"
#include "model.h"
#include "gen.h"

const ssize_t kMaxInstructionWidth = 32;

const char* kCHeader =
R"C(//
//  %s
//
//  DANGER - This is machine generated code
//

)C";

void rv_codec_node::clear()
{
	bits.clear();
	vals.clear();
	val_opcodes.clear();
	val_decodes.clear();
}

rv_gen::rv_gen()
{
	generators.push_back(std::make_shared<rv_gen_cc>(this));
	generators.push_back(std::make_shared<rv_gen_constraints>(this));
	generators.push_back(std::make_shared<rv_gen_fpu_test>(this));
	generators.push_back(std::make_shared<rv_gen_interp>(this));
	generators.push_back(std::make_shared<rv_gen_jit>(this));
	generators.push_back(std::make_shared<rv_gen_latex>(this));
	generators.push_back(std::make_shared<rv_gen_latex_alt>(this));
	generators.push_back(std::make_shared<rv_gen_map>(this));
	generators.push_back(std::make_shared<rv_gen_meta>(this));
	generators.push_back(std::make_shared<rv_gen_operands>(this));
	generators.push_back(std::make_shared<rv_gen_strings>(this));
	generators.push_back(std::make_shared<rv_gen_switch>(this));
	generators.push_back(std::make_shared<rv_gen_tablegen>(this));
}

void rv_gen::generate(int argc, const char *argv[])
{
	std::string isa_spec = "";
	bool help_or_error = false;

	// get generator command line options
	std::vector<cmdline_option> options = {
		{ "-h", "--help", cmdline_arg_type_none,
			"Show help",
			[&](std::string s) { return (help_or_error = true); } },
		{ "-I", "--isa-subset", cmdline_arg_type_string,
			"ISA subset (e.g. RV32IMA, RV32G, RV32GSC, RV64IMA, RV64G, RV64GSC)",
			[&](std::string s) { isa_spec = s; return true; } },
		{ "-r", "--read-isa", cmdline_arg_type_string,
			"Read instruction set metadata from directory",
			[&](std::string s) { return read_metadata(s); } },
		{ "-N", "--no-comment", cmdline_arg_type_none,
			"Don't emit comments in generated source",
			[&](std::string s) { return set_option("no_comment"); } },
		{ "-0", "--numeric-constants", cmdline_arg_type_none,
			"Use numeric constants in generated source",
			[&](std::string s) { return set_option("zero_not_oh"); } },
	};
	for (auto &gen : generators) {
		auto gen_opts = gen->get_cmdline_options();
		std::copy(gen_opts.begin(), gen_opts.end(), std::back_inserter(options));
	}
	options.push_back(
		{ nullptr, nullptr, cmdline_arg_type_none,   nullptr, nullptr }
	);

	auto result = cmdline_option::process_options(options.data(), argc, argv);
	if (!result.second) {
		help_or_error = true;
	} else if (result.first.size() != 0) {
		printf("%s: wrong number of arguments\n", argv[0]);
		help_or_error = true;
	}
	if (help_or_error) {
		printf("usage: %s [<options>]\n", argv[0]);
		cmdline_option::print_options(options.data());
		exit(9);
	}

	ext_subset = decode_isa_extensions(isa_spec);
	generate_map();

	for (auto &gen : generators) {
		gen->generate();
	}
}

void rv_gen::generate_map()
{
	for (auto &opcode : all_opcodes) {
		for (auto &mask : opcode->masks) {
			ssize_t msb = mask.first.msb;
			ssize_t lsb = mask.first.lsb;
			ssize_t val = mask.second;
			for (ssize_t bit = msb; bit >= lsb; bit--) {
				opcode->mask |= (1ULL << bit);
				opcode->match |= ((uint64_t(val) >> (bit - lsb)) & 1) << bit;
			}
		}
	}
}

void rv_gen::generate_codec()
{
	// make list of opcodes to include
	rv_opcode_list opcodes_copy;
	for (auto &opcode : all_opcodes) {
		if (opcode->is_pseudo()) continue;
		opcodes_copy.push_back(opcode);
	}

	// generate decode
	root_node.clear();
	generate_codec_node(root_node, opcodes_copy);
}

void rv_gen::generate_codec_node(rv_codec_node &node, rv_opcode_list &opcode_list)
{
	// calculate row coverage for each column
	std::vector<ssize_t> sum;
	sum.resize(32);
	for (auto &opcode : opcode_list) {
		for (ssize_t bit = kMaxInstructionWidth-1; bit >= 0; bit--) {
			if ((opcode->mask & (1 << bit)) && !(opcode->done & (1 << bit))) sum[bit]++;
		}
	}

	// find column with maximum row coverage
	ssize_t max_rows = 0;
	for (ssize_t bit = kMaxInstructionWidth-1; bit >= 0; bit--) {
		if (sum[bit] > max_rows) max_rows = sum[bit];
	}

	if (max_rows == 0) return; // no bits to match

	// select bits that cover maximum number of rows
	for (ssize_t bit = kMaxInstructionWidth-1; bit >= 0; bit--) {
		if (sum[bit] == max_rows) node.bits.push_back(bit);
	}

	// find distinct values for the chosen bits
	for (auto &opcode : opcode_list) {

		ssize_t val = 0;
		bool partial_match = false;
		for (auto &bit : node.bits) {
			if (!(opcode->mask & (1 << bit))) {
				partial_match = true;
			} else {
				val = (val << 1) | ((opcode->match & (1 << bit)) ? 1 : 0);
			}
		}

		// partial match is default in switch containing more specific masks
		if (partial_match) {
			val = DEFAULT;
		}

		// add value to list
		if (std::find(node.vals.begin(), node.vals.end(), val) == node.vals.end()) {
			node.vals.push_back(val);
		}

		// create opcode list for this value and add opcode to the list
		auto val_opcode_list_i = node.val_opcodes.find(val);
		if (val_opcode_list_i == node.val_opcodes.end()) {
			val_opcode_list_i = node.val_opcodes.insert(node.val_opcodes.begin(),
				std::pair<ssize_t,rv_opcode_list>(val, rv_opcode_list()));
		}
		val_opcode_list_i->second.push_back(opcode);
	}

	// sort values
	std::sort(node.vals.begin(), node.vals.end());

	// mark chosen bits as done
	for (auto &opcode : opcode_list) {
		for (auto &bit : node.bits) {
			opcode->done |= (1 << bit);
		}
	}

	// recurse
	for (auto &val : node.vals) {
		if (node.val_decodes.find(val) == node.val_decodes.end()) {
			node.val_decodes.insert(node.val_decodes.begin(),
				std::pair<ssize_t,rv_codec_node>(val, rv_codec_node()));
		}
		generate_codec_node(node.val_decodes[val], node.val_opcodes[val]);
	}
}

/* main */

int main(int argc, const char *argv[])
{
	rv_gen gen;
	gen.generate(argc, argv);
	exit(0);
}
<commit_msg>Remove include <sstream> from rv-meta<commit_after>//
//  rv-meta.cc
//

#include <cstdio>
#include <functional>
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include <deque>
#include <map>
#include <set>

#include "util.h"
#include "cmdline.h"
#include "model.h"
#include "gen.h"

const ssize_t kMaxInstructionWidth = 32;

const char* kCHeader =
R"C(//
//  %s
//
//  DANGER - This is machine generated code
//

)C";

void rv_codec_node::clear()
{
	bits.clear();
	vals.clear();
	val_opcodes.clear();
	val_decodes.clear();
}

rv_gen::rv_gen()
{
	generators.push_back(std::make_shared<rv_gen_cc>(this));
	generators.push_back(std::make_shared<rv_gen_constraints>(this));
	generators.push_back(std::make_shared<rv_gen_fpu_test>(this));
	generators.push_back(std::make_shared<rv_gen_interp>(this));
	generators.push_back(std::make_shared<rv_gen_jit>(this));
	generators.push_back(std::make_shared<rv_gen_latex>(this));
	generators.push_back(std::make_shared<rv_gen_latex_alt>(this));
	generators.push_back(std::make_shared<rv_gen_map>(this));
	generators.push_back(std::make_shared<rv_gen_meta>(this));
	generators.push_back(std::make_shared<rv_gen_operands>(this));
	generators.push_back(std::make_shared<rv_gen_strings>(this));
	generators.push_back(std::make_shared<rv_gen_switch>(this));
	generators.push_back(std::make_shared<rv_gen_tablegen>(this));
}

void rv_gen::generate(int argc, const char *argv[])
{
	std::string isa_spec = "";
	bool help_or_error = false;

	// get generator command line options
	std::vector<cmdline_option> options = {
		{ "-h", "--help", cmdline_arg_type_none,
			"Show help",
			[&](std::string s) { return (help_or_error = true); } },
		{ "-I", "--isa-subset", cmdline_arg_type_string,
			"ISA subset (e.g. RV32IMA, RV32G, RV32GSC, RV64IMA, RV64G, RV64GSC)",
			[&](std::string s) { isa_spec = s; return true; } },
		{ "-r", "--read-isa", cmdline_arg_type_string,
			"Read instruction set metadata from directory",
			[&](std::string s) { return read_metadata(s); } },
		{ "-N", "--no-comment", cmdline_arg_type_none,
			"Don't emit comments in generated source",
			[&](std::string s) { return set_option("no_comment"); } },
		{ "-0", "--numeric-constants", cmdline_arg_type_none,
			"Use numeric constants in generated source",
			[&](std::string s) { return set_option("zero_not_oh"); } },
	};
	for (auto &gen : generators) {
		auto gen_opts = gen->get_cmdline_options();
		std::copy(gen_opts.begin(), gen_opts.end(), std::back_inserter(options));
	}
	options.push_back(
		{ nullptr, nullptr, cmdline_arg_type_none,   nullptr, nullptr }
	);

	auto result = cmdline_option::process_options(options.data(), argc, argv);
	if (!result.second) {
		help_or_error = true;
	} else if (result.first.size() != 0) {
		printf("%s: wrong number of arguments\n", argv[0]);
		help_or_error = true;
	}
	if (help_or_error) {
		printf("usage: %s [<options>]\n", argv[0]);
		cmdline_option::print_options(options.data());
		exit(9);
	}

	ext_subset = decode_isa_extensions(isa_spec);
	generate_map();

	for (auto &gen : generators) {
		gen->generate();
	}
}

void rv_gen::generate_map()
{
	for (auto &opcode : all_opcodes) {
		for (auto &mask : opcode->masks) {
			ssize_t msb = mask.first.msb;
			ssize_t lsb = mask.first.lsb;
			ssize_t val = mask.second;
			for (ssize_t bit = msb; bit >= lsb; bit--) {
				opcode->mask |= (1ULL << bit);
				opcode->match |= ((uint64_t(val) >> (bit - lsb)) & 1) << bit;
			}
		}
	}
}

void rv_gen::generate_codec()
{
	// make list of opcodes to include
	rv_opcode_list opcodes_copy;
	for (auto &opcode : all_opcodes) {
		if (opcode->is_pseudo()) continue;
		opcodes_copy.push_back(opcode);
	}

	// generate decode
	root_node.clear();
	generate_codec_node(root_node, opcodes_copy);
}

void rv_gen::generate_codec_node(rv_codec_node &node, rv_opcode_list &opcode_list)
{
	// calculate row coverage for each column
	std::vector<ssize_t> sum;
	sum.resize(32);
	for (auto &opcode : opcode_list) {
		for (ssize_t bit = kMaxInstructionWidth-1; bit >= 0; bit--) {
			if ((opcode->mask & (1 << bit)) && !(opcode->done & (1 << bit))) sum[bit]++;
		}
	}

	// find column with maximum row coverage
	ssize_t max_rows = 0;
	for (ssize_t bit = kMaxInstructionWidth-1; bit >= 0; bit--) {
		if (sum[bit] > max_rows) max_rows = sum[bit];
	}

	if (max_rows == 0) return; // no bits to match

	// select bits that cover maximum number of rows
	for (ssize_t bit = kMaxInstructionWidth-1; bit >= 0; bit--) {
		if (sum[bit] == max_rows) node.bits.push_back(bit);
	}

	// find distinct values for the chosen bits
	for (auto &opcode : opcode_list) {

		ssize_t val = 0;
		bool partial_match = false;
		for (auto &bit : node.bits) {
			if (!(opcode->mask & (1 << bit))) {
				partial_match = true;
			} else {
				val = (val << 1) | ((opcode->match & (1 << bit)) ? 1 : 0);
			}
		}

		// partial match is default in switch containing more specific masks
		if (partial_match) {
			val = DEFAULT;
		}

		// add value to list
		if (std::find(node.vals.begin(), node.vals.end(), val) == node.vals.end()) {
			node.vals.push_back(val);
		}

		// create opcode list for this value and add opcode to the list
		auto val_opcode_list_i = node.val_opcodes.find(val);
		if (val_opcode_list_i == node.val_opcodes.end()) {
			val_opcode_list_i = node.val_opcodes.insert(node.val_opcodes.begin(),
				std::pair<ssize_t,rv_opcode_list>(val, rv_opcode_list()));
		}
		val_opcode_list_i->second.push_back(opcode);
	}

	// sort values
	std::sort(node.vals.begin(), node.vals.end());

	// mark chosen bits as done
	for (auto &opcode : opcode_list) {
		for (auto &bit : node.bits) {
			opcode->done |= (1 << bit);
		}
	}

	// recurse
	for (auto &val : node.vals) {
		if (node.val_decodes.find(val) == node.val_decodes.end()) {
			node.val_decodes.insert(node.val_decodes.begin(),
				std::pair<ssize_t,rv_codec_node>(val, rv_codec_node()));
		}
		generate_codec_node(node.val_decodes[val], node.val_opcodes[val]);
	}
}

/* main */

int main(int argc, const char *argv[])
{
	rv_gen gen;
	gen.generate(argc, argv);
	exit(0);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017-2018 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __BASE_REFCNT_HH__
#define __BASE_REFCNT_HH__

#include <type_traits>

/**
 * @file base/refcnt.hh
 *
 * Classes for managing reference counted objects.
 */

/**
 * Derive from RefCounted if you want to enable reference counting of
 * this class.  If you want to use automatic reference counting, you
 * should use RefCountingPtr<T> instead of regular pointers.
 */
class RefCounted
{
  private:
    // The reference count is mutable because one may want to
    // reference count a const pointer.  This really is OK because
    // const is about logical constness of the object not really about
    // strictly disallowing an object to change.
    mutable int count;

  private:
    // Don't allow a default copy constructor or copy operator on
    // these objects because the default operation will copy the
    // reference count as well and we certainly don't want that.
    RefCounted(const RefCounted &);
    RefCounted &operator=(const RefCounted &);

  public:
    /**
     * We initialize the reference count to zero and the first object
     * to take ownership of it must increment it to one.
     *
     * @attention A memory leak will occur if you never assign a newly
     * constructed object to a reference counting pointer.
     */
    RefCounted() : count(0) {}

    /**
     * We make the destructor virtual because we're likely to have
     * virtual functions on reference counted objects.
     *
     * @todo Even if this were true, does it matter?  Shouldn't the
     * derived class indicate this?  This only matters if we would
     * ever choose to delete a "RefCounted *" which I doubt we'd ever
     * do.  We don't ever delete a "void *".
     */
    virtual ~RefCounted() {}

    /// Increment the reference count
    void incref() const { ++count; }

    /// Decrement the reference count and destroy the object if all
    /// references are gone.
    void decref() const { if (--count <= 0) delete this; }
};

/**
 * If you want a reference counting pointer to a mutable object,
 * create it like this:
 * @code
 * typedef RefCountingPtr<Foo> FooPtr;
 * @endcode
 *
 * @attention Do not use "const FooPtr"
 * To create a reference counting pointer to a const object, use this:
 * @code
 * typedef RefCountingPtr<const Foo> ConstFooPtr;
 * @endcode
 *
 * These two usages are analogous to iterator and const_iterator in the stl.
 */
template <class T>
class RefCountingPtr
{
  public:
    using PtrType = T*;

  protected:
    /** Convenience aliases for const/non-const versions of T w/ friendship. */
    /** @{ */
    static constexpr auto TisConst = std::is_const<T>::value;
    using ConstT = typename std::conditional<TisConst,
            RefCountingPtr<T>,
            RefCountingPtr<typename std::add_const<T>::type>>::type;
    friend ConstT;
    using NonConstT = typename std::conditional<TisConst,
            RefCountingPtr<typename std::remove_const<T>::type>,
            RefCountingPtr<T>>::type;
    friend NonConstT;
    /** @} */
    /// The stored pointer.
    /// Arguably this should be private.
    T *data;

    /**
     * Copy a new pointer value and increment the reference count if
     * it is a valid pointer.  Note, this does not delete the
     * reference any existing object.
     * @param d Pointer to store.
     */
    void
    copy(T *d)
    {
        data = d;
        if (data)
            data->incref();
    }

    /**
     * Delete the reference to any existing object if it is non NULL.
     * @attention this doesn't clear the pointer value, so a double
     * decref could happen if not careful.
     */
    void
    del()
    {
        if (data)
            data->decref();
    }

    /**
     * Drop the old reference and change it to something new.
     */
    void
    set(T *d)
    {
        // Need to check if we're actually changing because otherwise
        // we could delete the last reference before adding the new
        // reference.
        if (data != d) {
            del();
            copy(d);
        }
    }

  public:
    /// Create an empty reference counting pointer.
    RefCountingPtr() : data(0) {}

    /// Create a new reference counting pointer to some object
    /// (probably something newly created).  Adds a reference.
    RefCountingPtr(T *data) { copy(data); }

    /// Create a new reference counting pointer by copying another
    /// one.  Adds a reference.
    RefCountingPtr(const RefCountingPtr &r) { copy(r.data); }

    /** Move-constructor.
     * Does not add a reference.
     */
    RefCountingPtr(RefCountingPtr&& r)
    {
        data = r.data;
        r.data = nullptr;
    }

    template <bool B = TisConst>
    RefCountingPtr(const NonConstT &r) { copy(r.data); }

    /// Destroy the pointer and any reference it may hold.
    ~RefCountingPtr() { del(); }

    // The following pointer access functions are const because they
    // don't actually change the pointer, though the user could change
    // what is pointed to.  This is analagous to a "Foo * const".

    /// Access a member variable.
    T *operator->() const { return data; }

    /// Dereference the pointer.
    T &operator*() const { return *data; }

    /// Directly access the pointer itself without taking a reference.
    T *get() const { return data; }

    template <bool B = TisConst>
    operator RefCountingPtr<typename std::enable_if_t<!B, ConstT>>()
    {
        return RefCountingPtr<const T>(*this);
    }

    /// Assign a new value to the pointer
    const RefCountingPtr &operator=(T *p) { set(p); return *this; }

    /// Copy the pointer from another RefCountingPtr
    const RefCountingPtr &operator=(const RefCountingPtr &r)
    { return operator=(r.data); }

    /// Move-assign the pointer from another RefCountingPtr
    const RefCountingPtr &operator=(RefCountingPtr&& r)
    {
        /* This happens regardless of whether the pointer is the same or not,
         * because of the move semantics, the rvalue needs to be 'destroyed'.
         */
        del();
        data = r.data;
        r.data = nullptr;
        return *this;
    }

    /// Check if the pointer is empty
    bool operator!() const { return data == 0; }

    /// Check if the pointer is non-empty
    operator bool() const { return data != 0; }
};

/// Check for equality of two reference counting pointers.
template<class T>
inline bool operator==(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
{ return l.get() == r.get(); }

/// Check for equality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool operator==(const RefCountingPtr<T> &l, const T *r)
{ return l.get() == r; }

/// Check for equality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool operator==(const T *l, const RefCountingPtr<T> &r)
{ return l == r.get(); }

/// Check for inequality of two reference counting pointers.
template<class T>
inline bool operator!=(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
{ return l.get() != r.get(); }

/// Check for inequality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool operator!=(const RefCountingPtr<T> &l, const T *r)
{ return l.get() != r; }

/// Check for inequality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool operator!=(const T *l, const RefCountingPtr<T> &r)
{ return l != r.get(); }

#endif // __BASE_REFCNT_HH__
<commit_msg>base: Style fixes in base/refcnt.hh<commit_after>/*
 * Copyright (c) 2017-2018 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __BASE_REFCNT_HH__
#define __BASE_REFCNT_HH__

#include <type_traits>

/**
 * @file base/refcnt.hh
 *
 * Classes for managing reference counted objects.
 */

/**
 * Derive from RefCounted if you want to enable reference counting of
 * this class.  If you want to use automatic reference counting, you
 * should use RefCountingPtr<T> instead of regular pointers.
 */
class RefCounted
{
  private:
    // The reference count is mutable because one may want to
    // reference count a const pointer.  This really is OK because
    // const is about logical constness of the object not really about
    // strictly disallowing an object to change.
    mutable int count;

  private:
    // Don't allow a default copy constructor or copy operator on
    // these objects because the default operation will copy the
    // reference count as well and we certainly don't want that.
    RefCounted(const RefCounted &);
    RefCounted &operator=(const RefCounted &);

  public:
    /**
     * We initialize the reference count to zero and the first object
     * to take ownership of it must increment it to one.
     *
     * @attention A memory leak will occur if you never assign a newly
     * constructed object to a reference counting pointer.
     */
    RefCounted() : count(0) {}

    /**
     * We make the destructor virtual because we're likely to have
     * virtual functions on reference counted objects.
     *
     * @todo Even if this were true, does it matter?  Shouldn't the
     * derived class indicate this?  This only matters if we would
     * ever choose to delete a "RefCounted *" which I doubt we'd ever
     * do.  We don't ever delete a "void *".
     */
    virtual ~RefCounted() {}

    /// Increment the reference count
    void incref() const { ++count; }

    /// Decrement the reference count and destroy the object if all
    /// references are gone.
    void
    decref() const
    {
        if (--count <= 0)
            delete this;
    }
};

/**
 * If you want a reference counting pointer to a mutable object,
 * create it like this:
 * @code
 * typedef RefCountingPtr<Foo> FooPtr;
 * @endcode
 *
 * @attention Do not use "const FooPtr"
 * To create a reference counting pointer to a const object, use this:
 * @code
 * typedef RefCountingPtr<const Foo> ConstFooPtr;
 * @endcode
 *
 * These two usages are analogous to iterator and const_iterator in the stl.
 */
template <class T>
class RefCountingPtr
{
  public:
    using PtrType = T*;

  protected:
    /** Convenience aliases for const/non-const versions of T w/ friendship. */
    /** @{ */
    static constexpr auto TisConst = std::is_const<T>::value;
    using ConstT = typename std::conditional<TisConst,
            RefCountingPtr<T>,
            RefCountingPtr<typename std::add_const<T>::type>>::type;
    friend ConstT;
    using NonConstT = typename std::conditional<TisConst,
            RefCountingPtr<typename std::remove_const<T>::type>,
            RefCountingPtr<T>>::type;
    friend NonConstT;
    /** @} */
    /// The stored pointer.
    /// Arguably this should be private.
    T *data;

    /**
     * Copy a new pointer value and increment the reference count if
     * it is a valid pointer.  Note, this does not delete the
     * reference any existing object.
     * @param d Pointer to store.
     */
    void
    copy(T *d)
    {
        data = d;
        if (data)
            data->incref();
    }

    /**
     * Delete the reference to any existing object if it is non NULL.
     * @attention this doesn't clear the pointer value, so a double
     * decref could happen if not careful.
     */
    void
    del()
    {
        if (data)
            data->decref();
    }

    /**
     * Drop the old reference and change it to something new.
     */
    void
    set(T *d)
    {
        // Need to check if we're actually changing because otherwise
        // we could delete the last reference before adding the new
        // reference.
        if (data != d) {
            del();
            copy(d);
        }
    }

  public:
    /// Create an empty reference counting pointer.
    RefCountingPtr() : data(0) {}

    /// Create a new reference counting pointer to some object
    /// (probably something newly created).  Adds a reference.
    RefCountingPtr(T *data) { copy(data); }

    /// Create a new reference counting pointer by copying another
    /// one.  Adds a reference.
    RefCountingPtr(const RefCountingPtr &r) { copy(r.data); }

    /** Move-constructor.
     * Does not add a reference.
     */
    RefCountingPtr(RefCountingPtr&& r)
    {
        data = r.data;
        r.data = nullptr;
    }

    template <bool B = TisConst>
    RefCountingPtr(const NonConstT &r) { copy(r.data); }

    /// Destroy the pointer and any reference it may hold.
    ~RefCountingPtr() { del(); }

    // The following pointer access functions are const because they
    // don't actually change the pointer, though the user could change
    // what is pointed to.  This is analagous to a "Foo * const".

    /// Access a member variable.
    T *operator->() const { return data; }

    /// Dereference the pointer.
    T &operator*() const { return *data; }

    /// Directly access the pointer itself without taking a reference.
    T *get() const { return data; }

    template <bool B = TisConst>
    operator RefCountingPtr<typename std::enable_if_t<!B, ConstT>>()
    {
        return RefCountingPtr<const T>(*this);
    }

    /// Assign a new value to the pointer
    const RefCountingPtr &operator=(T *p) { set(p); return *this; }

    /// Copy the pointer from another RefCountingPtr
    const RefCountingPtr &
    operator=(const RefCountingPtr &r)
    {
        return operator=(r.data);
    }

    /// Move-assign the pointer from another RefCountingPtr
    const RefCountingPtr &
    operator=(RefCountingPtr&& r)
    {
        /* This happens regardless of whether the pointer is the same or not,
         * because of the move semantics, the rvalue needs to be 'destroyed'.
         */
        del();
        data = r.data;
        r.data = nullptr;
        return *this;
    }

    /// Check if the pointer is empty
    bool operator!() const { return data == 0; }

    /// Check if the pointer is non-empty
    operator bool() const { return data != 0; }
};

/// Check for equality of two reference counting pointers.
template<class T>
inline bool
operator==(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
{
    return l.get() == r.get();
}

/// Check for equality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool
operator==(const RefCountingPtr<T> &l, const T *r)
{
    return l.get() == r;
}

/// Check for equality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool
operator==(const T *l, const RefCountingPtr<T> &r)
{
    return l == r.get();
}

/// Check for inequality of two reference counting pointers.
template<class T>
inline bool
operator!=(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
{
    return l.get() != r.get();
}

/// Check for inequality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool
operator!=(const RefCountingPtr<T> &l, const T *r)
{
    return l.get() != r;
}

/// Check for inequality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool
operator!=(const T *l, const RefCountingPtr<T> &r)
{
    return l != r.get();
}

#endif // __BASE_REFCNT_HH__
<|endoftext|>


<commit_before>#include <cmath>
#include <iostream>
#include "RandomNumberGenerator.h"

#include "RJObject.h"

using namespace std;
using namespace DNest3;

RJObject::RJObject(int num_dimensions, int max_num_components)
:num_dimensions(num_dimensions)
,max_num_components(max_num_components)
,positions(max_num_components, vector<double>(num_dimensions))
,masses(max_num_components)
{

}

void RJObject::fromPrior()
{
	// Generate from {0, 1, 2, ..., max_num_components}
	num_components = randInt(max_num_components + 1);

	// Assign positions and masses
	for(int i=0; i<num_components; i++)
	{
		for(int j=0; j<num_dimensions; j++)
			positions[i][j] = -1. + 2.*randomU(); // Default domain
		masses[i] = mass_cdf_inv(randomU());
	}
}

// Exponential distribution
double RJObject::mass_log_pdf(double x) const
{
	if(x <= 0.)
		return -1E300;
	return -x;
}

double RJObject::mass_cdf(double x) const
{
	if(x <= 0.)
		return 0.;
	return 1. - exp(-x);
}

double RJObject::mass_cdf_inv(double u) const
{
	if(u < 0. || u > 1.)
	{
		cerr<<"# WARNING: Attempted to call inverse CDF on ";
		cerr<<"an argument not in [0, 1]."<<endl;
	}
	return -log(1. - u);
}

ostream& operator << (ostream& out, const RJObject& r)
{
	out<<r.num_dimensions<<' '<<r.max_num_components<<' ';
	// Write out positions and masses
	for(int i=0; i<r.num_components; i++)
	{
		for(int j=0; j<r.num_dimensions; j++)
			out<<r.positions[i][j]<<' ';
		out<<r.masses[i]<<' ';
	}
	return out;
}

// Demonstration of the class
int main()
{
	RJObject r(2, 100);
	r.fromPrior();
	cout<<r<<endl;
	return 0;
}

<commit_msg>Fixed segfault (forgot to initialise DNest's RNG), made output sensible<commit_after>#include <cmath>
#include <iostream>
#include <iomanip>
#include "RandomNumberGenerator.h"

#include "RJObject.h"

using namespace std;
using namespace DNest3;

RJObject::RJObject(int num_dimensions, int max_num_components)
:num_dimensions(num_dimensions)
,max_num_components(max_num_components)
,positions(max_num_components, vector<double>(num_dimensions))
,masses(max_num_components)
{

}

void RJObject::fromPrior()
{
	// Generate from {0, 1, 2, ..., max_num_components}
	num_components = randInt(max_num_components + 1);

	// Assign positions and masses
	for(int i=0; i<num_components; i++)
	{
		for(int j=0; j<num_dimensions; j++)
			positions[i][j] = -1. + 2.*randomU(); // Default domain
		masses[i] = mass_cdf_inv(randomU());
	}
}

// Exponential distribution
double RJObject::mass_log_pdf(double x) const
{
	if(x <= 0.)
		return -1E300;
	return -x;
}

double RJObject::mass_cdf(double x) const
{
	if(x <= 0.)
		return 0.;
	return 1. - exp(-x);
}

double RJObject::mass_cdf_inv(double u) const
{
	if(u < 0. || u > 1.)
	{
		cerr<<"# WARNING: Attempted to call inverse CDF on ";
		cerr<<"an argument not in [0, 1]."<<endl;
	}
	return -log(1. - u);
}

ostream& operator << (ostream& out, const RJObject& r)
{
	out<<setprecision(12);
	out<<r.num_dimensions<<' '<<r.max_num_components<<' ';

	// Write out positions (all of first coordinate,
	// then all of second coordinate, etc)
	for(int j=0; j<r.num_dimensions; j++)
	{
		for(int i=0; i<r.num_components; i++)
			out<<r.positions[i][j]<<' ';

		// Pad with zeros (turned-off components)
		for(int i=r.num_components; i<r.max_num_components; i++)
			out<<0.<<' ';
	}

	// Write out masses
	for(int i=0; i<r.num_components; i++)
		out<<r.masses[i]<<' ';

	// Pad with zeros (turned-off components)
	for(int i=r.num_components; i<r.max_num_components; i++)
		out<<0.<<' ';

	return out;
}

#include <ctime>
// Demonstration of the class
int main()
{
	RandomNumberGenerator::initialise_instance();
	RandomNumberGenerator::get_instance().set_seed(time(0));

	RJObject r(2, 100);
	r.fromPrior();
	cout<<r<<endl;
	return 0;
}

<|endoftext|>


<commit_before>#include "RJObject.h"

<commit_msg>Implement constructor<commit_after>#include "RJObject.h"

using namespace std;

RJObject::RJObject(int num_dimensions, int max_num_objects)
:positions(max_num_objects, vector<double>(num_dimensions))
,masses(max_num_objects)
{

}

<|endoftext|>


<commit_before>#include "Renderer.h"

float Renderer::TileScale;
float Renderer::SpriteScale;

void Renderer::GetWallTile(Field *field, std::size_t x, std::size_t y,
		int &index, int &rotation, bool &flip)
{
	uint8_t neighborhood = 0x00;
	uint8_t edges = 0x00;
	field->NeighborhoodInfo(
			x, y, Field::Wall, Field::Edge, neighborhood, edges);

	for (int i = 0; i < 4; i++)
	{
		if (((neighborhood & 0xD5) == 0x41)
				&& ((edges & 0x06) == 0x06))
		{
			index = 1;
			rotation = i;
			flip = false;
			return;
		}
		else if (neighborhood == 0x47)
		{
			index = 2;
			rotation = i;
			flip = false;
			return;
		}
		else if (neighborhood == 0x5C)
		{
			index = 2;
			rotation = i;
			flip = true;
			return;
		}
		else if ((neighborhood & 0x45) == 0x01)
		{
			index = 3;
			rotation = i;
			flip = false;
			if ((edges & 0x08) == 0x08)
			{
				rotation = (2 + i) % 4;
			}
			return;
		}
		else if ((neighborhood & 0x5F) == 0x1F)
		{
			index = 4;
			rotation = i;
			flip = false;
			return;
		}
		else if (((neighborhood & 0x55) == 0x14)
				&& ((edges & 0x09) == 0x00))
		{
			index = 5;
			rotation = i;
			flip = false;
			return;
		}
		else if (neighborhood == 0x7F)
		{
			index = 6;
			rotation = i;
			flip = false;
			return;
		}

		neighborhood = (neighborhood << 2) + (neighborhood >> 6);
		edges = ((edges << 1) + (edges >> 3)) & 0x0F;
	}

	index = 0;
	rotation = 0;
	flip = false;
}

void Renderer::GetBoxTile(Field *field, std::size_t x, std::size_t y,
		int &index, int &rotation, bool &flip)
{
	uint8_t neighborhood = 0x00;
	uint8_t edges = 0x00;
	field->NeighborhoodInfo(
			x, y, Field::GhostBox, Field::GhostZone, neighborhood, edges);
	for (int i = 0; i < 4; i++)
	{
		if (((neighborhood & 0x55) == 0x14)
				&& ((edges & 0x09) == 0x00))
		{
			index = 7;
			rotation = i;
			flip = false;
			return;
		}
		else if ((neighborhood & 0x45) == 0x01)
		{
			index = 3;
			rotation = i;
			flip = false;
			if ((edges & 0x08) == 0x08)
			{
				rotation = (2 + i) % 4;
			}
			return;
		}
		neighborhood = (neighborhood << 2) + (neighborhood >> 6);
		edges = ((edges << 1) + (edges >> 3)) & 0x0F;
	}
}
<commit_msg>Explicitly defined bitfield for neighborhood<commit_after>#include "Renderer.h"

float Renderer::TileScale;
float Renderer::SpriteScale;

#define NB_N  0x00
#define NB_R  0x01
#define NB_UR 0x02
#define NB_U  0x04
#define NB_UL 0x08
#define NB_L  0x10
#define NB_DL 0x20
#define NB_D  0x40
#define NB_DR 0x80
#define ED_N  0x00
#define ED_R  0x01
#define ED_U  0x02
#define ED_L  0x04
#define ED_D  0x08

void Renderer::GetWallTile(Field *field, std::size_t x, std::size_t y,
		int &index, int &rotation, bool &flip)
{
	uint8_t neighborhood = 0x00;
	uint8_t edges = 0x00;
	field->NeighborhoodInfo(
			x, y, Field::Wall, Field::Edge, neighborhood, edges);

	for (int i = 0; i < 4; i++)
	{
		if (((neighborhood & (NB_R|NB_U|NB_UL)) == (NB_R|NB_D))
				&& ((edges & (ED_U|ED_L)) == (ED_U|ED_L)))
		{
			index = 1;
			rotation = i;
			flip = false;
			return;
		}
		else if (neighborhood == (NB_R|NB_UR|NB_U|NB_D))
		{
			index = 2;
			rotation = i;
			flip = false;
			return;
		}
		else if (neighborhood == (NB_U|NB_UL|NB_L|NB_D))
		{
			index = 2;
			rotation = i;
			flip = true;
			return;
		}
		else if ((neighborhood & (NB_R|NB_U|NB_D)) == NB_R)
		{
			index = 3;
			rotation = i;
			flip = false;
			if ((edges & ED_D) == ED_D)
			{
				rotation = (2 + i) % 4;
			}
			return;
		}
		else if ((neighborhood & (NB_R|NB_UR|NB_L|NB_UL|NB_L|NB_D))
				== (NB_R|NB_UR|NB_L|NB_UL|NB_L))
		{
			index = 4;
			rotation = i;
			flip = false;
			return;
		}
		else if (((neighborhood & (NB_R|NB_U|NB_L|NB_D)) == (NB_U|NB_L))
				&& ((edges & (ED_R|ED_D)) == ED_N))
		{
			index = 5;
			rotation = i;
			flip = false;
			return;
		}
		else if (neighborhood == (NB_R|NB_UR|NB_U|NB_UL|NB_L|NB_DL|NB_D))
		{
			index = 6;
			rotation = i;
			flip = false;
			return;
		}

		neighborhood = (neighborhood << 2) + (neighborhood >> 6);
		edges = ((edges << 1) + (edges >> 3)) & 0x0F;
	}

	index = 0;
	rotation = 0;
	flip = false;
}

void Renderer::GetBoxTile(Field *field, std::size_t x, std::size_t y,
		int &index, int &rotation, bool &flip)
{
	uint8_t neighborhood;
	uint8_t edges;
	field->NeighborhoodInfo(
			x, y, Field::GhostBox, Field::GhostZone, neighborhood, edges);
	for (int i = 0; i < 4; i++)
	{
		if (((neighborhood & (NB_R|NB_U|NB_L|NB_D)) == (NB_U|NB_L))
				&& ((edges & (ED_R|ED_D)) == (ED_N)))
		{
			index = 7;
			rotation = i;
			flip = false;
			return;
		}
		else if ((neighborhood & (NB_R|NB_U|NB_D)) == NB_R)
		{
			index = 3;
			rotation = i;
			flip = false;
			if ((edges & ED_D) == ED_D)
			{
				rotation = (2 + i) % 4;
			}
			return;
		}
		neighborhood = (neighborhood << 2) + (neighborhood >> 6);
		edges = ((edges << 1) + (edges >> 3)) & 0x0F;
	}
}
<|endoftext|>