<commit_before>#include "../test.h"
#include "../image_comparer.h"
#include <QFile>
#include "../../src/placement/constraint_updater.h"
#include "../../src/graphics/qimage_drawer.h"

// TODO refactor test. Extract image comparison logic
//
TEST(Test_ConstraintUpdater, DrawWithConnectorShadows)
{
  int width = 512;
  int height = 256;
  auto drawer = std::make_shared<Graphics::QImageDrawer>(width, height);
  ConstraintUpdater constraintUpdater(drawer, width, height);
  constraintUpdater.setIsConnectorShadowEnabled(true);

  constraintUpdater.clear();

  Eigen::Vector2i anchorPosition(100, 50);
  Eigen::Vector2i labelSize(62, 20);
  Eigen::Vector2i lastAnchorPosition(200, 70);
  Eigen::Vector2i lastLabelPosition(150, 120);
  Eigen::Vector2i lastLabelSize(60, 40);
  constraintUpdater.drawConstraintRegionFor(anchorPosition, labelSize,
                                            lastAnchorPosition,
                                            lastLabelPosition, lastLabelSize);

  compareImages("expected-constraints-with-connectors.png",
                "constraints-with-connectors.png", drawer->image.get());
}

TEST(Test_ConstraintUpdater, DrawWithoutConnectorShadows)
{
  int width = 512;
  int height = 256;
  auto drawer = std::make_shared<Graphics::QImageDrawer>(width, height);
  ConstraintUpdater constraintUpdater(drawer, width, height);
  constraintUpdater.setIsConnectorShadowEnabled(false);

  constraintUpdater.clear();

  Eigen::Vector2i anchorPosition(100, 50);
  Eigen::Vector2i labelSize(62, 20);
  Eigen::Vector2i lastAnchorPosition(200, 70);
  Eigen::Vector2i lastLabelPosition(150, 120);
  Eigen::Vector2i lastLabelSize(60, 40);
  constraintUpdater.drawConstraintRegionFor(anchorPosition, labelSize,
                                            lastAnchorPosition,
                                            lastLabelPosition, lastLabelSize);

  compareImages("expected-constraints-without-connectors.png",
                "constraints-without-connectors.png", drawer->image.get());
}

<commit_msg>Extract Fixture for Test_ConstraintUpdater.<commit_after>#include "../test.h"
#include "../image_comparer.h"
#include <QFile>
#include "../../src/placement/constraint_updater.h"
#include "../../src/graphics/qimage_drawer.h"

class Test_ConstraintUpdater : public ::testing::Test
{
 protected:
  virtual void SetUp()
  {
    int width = 512;
    int height = 256;
    drawer = std::make_shared<Graphics::QImageDrawer>(width, height);
    constraintUpdater =
        std::make_shared<ConstraintUpdater>(drawer, width, height);
  }

 public:
  std::shared_ptr<Graphics::QImageDrawer> drawer;
  std::shared_ptr<ConstraintUpdater> constraintUpdater;

  void drawConstraintRegion()
  {
    constraintUpdater->clear();

    Eigen::Vector2i anchorPosition(100, 50);
    Eigen::Vector2i labelSize(62, 20);
    Eigen::Vector2i lastAnchorPosition(200, 70);
    Eigen::Vector2i lastLabelPosition(150, 120);
    Eigen::Vector2i lastLabelSize(60, 40);
    constraintUpdater->drawConstraintRegionFor(
        anchorPosition, labelSize, lastAnchorPosition, lastLabelPosition,
        lastLabelSize);
  }
};

TEST_F(Test_ConstraintUpdater, DrawWithConnectorShadows)
{
  constraintUpdater->setIsConnectorShadowEnabled(true);

  drawConstraintRegion();

  compareImages("expected-constraints-with-connectors.png",
                "constraints-with-connectors.png", drawer->image.get());
}

TEST_F(Test_ConstraintUpdater, DrawWithoutConnectorShadows)
{
  constraintUpdater->setIsConnectorShadowEnabled(false);

  drawConstraintRegion();

  compareImages("expected-constraints-without-connectors.png",
                "constraints-without-connectors.png", drawer->image.get());
}

<|endoftext|>


<commit_before>#include "builtin/block_environment.hpp"
#include "builtin/class.hpp"
#include "builtin/compiledmethod.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/lookuptable.hpp"
#include "builtin/tuple.hpp"

#include "gc_object_mark.hpp"
#include "objectmemory.hpp"

#include "vm/object_utils.hpp"

#include "builtin/contexts.hpp"
#include "builtin/nativemethodcontext.hpp"

#include <iostream>

namespace rubinius {

  void MethodContext::init(STATE) {
    GO(methctx).set(state->new_class("MethodContext", G(object)));
    G(methctx)->set_object_type(state, MethodContextType);

    GO(blokctx).set(state->new_class("BlockContext", G(methctx)));
    G(blokctx)->set_object_type(state, BlockContextType);
  }

  /* Initialize +ctx+'s fields */
  static inline void init_context(STATE, MethodContext* ctx, size_t stack) {
    ctx->StoresBytes = 1;
    ctx->ip = 0;
    ctx->native_ip = 0;
    ctx->current_unwind = 0;
    ctx->ivars(state, Qnil);

    // Do this here because it's possible for us to pass a context
    // around and it could leak out before the real sender is set.
    ctx->sender(state, (MethodContext*)Qnil);

    // Don't initialize any fields you KNOW are always set later
    // on before the ctx is used. We just waste precious time if we do.

    ctx->stack_size = stack;
    for(size_t i = 0; i < stack; i++) {
      ctx->stk[i] = Qnil;
    }

    ctx->js.stack = ctx->stk - 1;
    ctx->js.stack_top = (ctx->stk + stack - 1);
  }

  /* Find a context to use. Either use a cache or create one in the heap. */
  template <class T>
    static inline T* allocate(STATE, Class* cls, size_t stack_size) {
      T* ctx;

      ctx = reinterpret_cast<T*>(state->om->allocate_context(stack_size));
      if(ctx) {
        assert((uintptr_t)ctx + ctx->full_size < (uintptr_t)state->om->contexts.last);
        ctx->klass(state, (Class*)Qnil);
        ctx->obj_type = T::type;
      } else {
        // We're going to end up referencing a stack context from a heap
        // context, so we need to be sure all stack contexts stick around!
        state->om->clamp_contexts();
        ctx = state->new_struct<T>(cls, stack_size * sizeof(Object*));
      }

      init_context(state, ctx, stack_size);
      return ctx;
    }

  int MethodContext::line(STATE) {
    if(cm_->nil_p()) return -2;        // trampoline context
    if(cm_->lines()->nil_p()) return -3;

    for(size_t i = 0; i < cm_->lines()->num_fields(); i++) {
      Tuple* entry = as<Tuple>(cm_->lines()->at(state, i));

      Fixnum* start_ip = as<Fixnum>(entry->at(state, 0));
      Fixnum* end_ip   = as<Fixnum>(entry->at(state, 1));
      Fixnum* line     = as<Fixnum>(entry->at(state, 2));

      if(start_ip->to_native() <= ip && end_ip->to_native() >= ip)
        return line->to_native();
    }

    return -1;
  }

  void MethodContext::post_copy(MethodContext* old) {
    this->js.stack_top = this->stk + (this->stack_size - 1);
    this->position_stack(old->calculate_sp());
    if(this->obj_type == MethodContextType) {
      assert(this->home() == old->home());
    }
  }

  /* Attempt to recycle +this+ context into the context cache, based
   * on it's size. Returns true if the context was recycled, otherwise
   * false. */
  bool MethodContext::recycle(STATE) {
    if(zone != YoungObjectZone) return false;
    return state->om->deallocate_context(this);
  }

  /* Create a ContextCache object and install it in +state+ */
  void MethodContext::initialize_cache(STATE) {
  }

  /* Zero out the caches. */
  void MethodContext::reset_cache(STATE) {
    state->om->clamp_contexts();
  }

  /* Return a new +MethodContext+ object, which needs +stack_size fields
   * worth of stack.
   */
  MethodContext* MethodContext::create(STATE, size_t stack_size) {
    return allocate<MethodContext>(state, G(methctx), stack_size);
  }

  /* Generate a MethodContext for the provided receiver and CompiledMethod
   * The returned MethodContext is in an 'initial' state. The caller is
   * expected to SET any fields it needs to, e.g. +module+
   */
  MethodContext* MethodContext::create(STATE, Object* recv, CompiledMethod* meth) {
    size_t stack_size = meth->backend_method_->stack_size;

    MethodContext* ctx = state->om->allocate_context(stack_size);
    if(likely(ctx)) {
      ctx->klass_ = (Class*)Qnil;
      ctx->obj_type = MethodContextType;

      ctx->self_ = recv;
      ctx->cm_ = meth;
      ctx->home_ = ctx;

    } else {
      // We're going to end up referencing a stack context from a heap
      // context, so we need to be sure all stack contexts stick around!
      state->om->clamp_contexts();
      ctx = state->new_struct<MethodContext>(G(methctx), stack_size * sizeof(Object*));

      ctx->self(state, recv);
      ctx->cm(state, meth);
      ctx->home(state, ctx);
    }

    init_context(state, ctx, stack_size);

    ctx->vmm = meth->backend_method_;
    ctx->run = ctx->vmm->run;

    // nil out just where the locals are
    native_int locals = ctx->vmm->number_of_locals;

    ctx->position_stack(locals - 1);

    return ctx;
  }

  /* Called as the context_dup primitive
   */
  MethodContext* MethodContext::dup(STATE) {
    MethodContext* ctx = create(state, this->stack_size);

    /* This ctx is escaping into Ruby-land */
    ctx->reference(state);

    ctx->sender(state, this->sender());
    ctx->self(state, this->self());
    ctx->cm(state, this->cm());
    ctx->module(state, this->module());
    ctx->block(state, this->block());
    ctx->name(state, this->name());

    ctx->home(state, this->home());
    this->home()->reference(state); // so that the closure won't be deallocated.

    /* Set the obj_type because we get called
     * for both BlockContext and MethodContext
     */
    ctx->obj_type = this->obj_type;

    ctx->vmm = this->vmm;
    ctx->run = this->run;
    ctx->js = this->js;
    ctx->ip = this->ip;
    ctx->native_ip = this->native_ip;
    ctx->args = this->args;
    ctx->stack_size = this->stack_size;

    ctx->full_size = this->full_size;
    ctx->current_unwind = this->current_unwind;

    for(int i = 0; i < this->current_unwind; i++) {
      ctx->unwinds[i] = this->unwinds[i];
    }

    for(size_t i = 0; i < this->stack_size; i++) {
      ctx->stk[i] = this->stk[i];
    }

    ctx->js.stack_top = ctx->stk + (ctx->stack_size - 1);
    ctx->position_stack(this->calculate_sp());

    /* Stack Management procedures. Make sure that we don't
     * miss object stored into the stack of a context
     */
    if(ctx->zone == MatureObjectZone) {
      state->om->remember_object(ctx);
    }

    return ctx;
  }

  MethodContext* MethodContext::dup_chain(STATE) {

    LookupTable* map = LookupTable::create(state);

    MethodContext* ret = this->dup(state);

    for(MethodContext* ctx = ret; !ctx->sender()->nil_p(); ctx = ctx->sender()) {
      MethodContext* old_sender = ctx->sender();
      ctx->sender(state, old_sender->dup(state));
      if(old_sender->obj_type == MethodContextType) {
        map->store(state, old_sender, ctx->sender());
      }
    }

    for(MethodContext* ctx = ret; !ctx->sender()->nil_p(); ctx = ctx->sender()) {
      if(ctx->obj_type == BlockContextType) {
        BlockEnvironment* old_env = as<BlockContext>(ctx)->env();
        Object* new_env_home = map->aref(state, (old_env->home()));
        if(new_env_home->nil_p()) continue;
        BlockEnvironment* new_env = old_env->dup(state);
        new_env->home(state, as<MethodContext>(new_env_home));
        ctx->block(state, new_env);
      }
    }

    for(MethodContext* ctx = this; !ctx->sender()->nil_p(); ctx = ctx->sender()) {
      if(ctx->obj_type == MethodContextType) {
        map->remove(state, ctx);
      }
    }

    return ret;
  }

  /* Retrieve the BlockEnvironment from +this+ BlockContext. We reuse the
   * block field from MethodContext and use a type-safe cast. */
  BlockEnvironment* BlockContext::env() {
    return as<BlockEnvironment>(block());
  }

  /* Called as the block_context_env primitive
   */
  BlockEnvironment* BlockContext::env(STATE) {
    return this->env();
  }

  /* Lazy initialize fields that might have been left uninitialized
   * when +this+ was only used in the context cache. */
  void MethodContext::initialize_as_reference(STATE) {
    switch(obj_type) {
    case MethodContext::type:
      this->klass(state, G(methctx));
      break;
    case BlockContext::type:
      this->klass(state, G(blokctx));
      break;
    case NativeMethodContext::type:
      break;
    default:
      abort();
    }
  }

  /* Called when a context is referenced. Typically, this is via the push_context
   * opcode or MethodContext#sender. */
  void MethodContext::reference(STATE) {
    state->om->reference_context(this);
    initialize_as_reference(state);
  }

  /* Retrieve a field within the context, referenced by name. This
   * is used as a primitive. */
  Object* MethodContext::get_internal_data(STATE, Fixnum* type) {
    switch(type->to_native()) {
    case 1:
      return Fixnum::from(ip);
    case 2:
      return Fixnum::from(calculate_sp());
    case 3:
      if(native_ip == 0) {
        return Qnil;
      } else {
        return Integer::from(state, reinterpret_cast<uintptr_t>(native_ip));
      }
    }

    sassert(0 && "invalid index");
    return Qnil;
  }

  Array* MethodContext::locals(STATE) {
    int n = this->vmm->number_of_locals;
    Array* ary = Array::create(state, n);
    for(int i = 0; i < n; i++) {
      ary->set(state, i, this->get_local(i));
    }
    return ary;
  }

  /* Return a new +BlockContext+ object, which needs +stack_size+ fields
   * worth of stack. */
  BlockContext* BlockContext::create(STATE, size_t stack_size) {
    BlockContext* ctx = allocate<BlockContext>(state, G(blokctx), stack_size);

    ctx->block(state, Qnil);
    ctx->cm(state, reinterpret_cast<CompiledMethod*>(Qnil));
    ctx->home(state, reinterpret_cast<MethodContext*>(Qnil));
    ctx->module(state, reinterpret_cast<Module*>(Qnil));
    ctx->name(state, Qnil);
    ctx->self(state, Qnil);
    ctx->sender(state, reinterpret_cast<MethodContext*>(Qnil));

    return ctx;
  }

  void MethodContext::Info::mark(Object* obj, ObjectMark& mark) {
    MethodContext* ctx = as<MethodContext>(obj);

    // Detect a context on the special context stack and fix it up.
    if(ctx->klass_->nil_p()) {
      ctx->initialize_as_reference(state());
    }

    // FIXME this is to help detect an ellusive bug
    if(!ctx->sender()->nil_p() &&
        (ctx->sender()->zone == UnspecifiedZone ||
         !ctx->sender()->StoresBytes)) {
      MethodContext* s = ctx->sender();
      std::cout << "Corrupt context detected!\n";
      std::cout << "origin = " << obj << "\n";
      std::cout << "object = " << s << "\n";
      std::cout << "full_size = " << s->full_size << "\n";
      std::cout << "klass = " << s->klass_ << "\n";

      ObjectPosition pos = mark.gc->object_memory->validate_object(ctx->sender());
      if(pos == cContextStack) {
        Assertion::raise("A sender on the context stack has an UnspecifiedZone");
      } else if(pos == cUnknown){
        Assertion::raise("A sender in unknown memory has an UnspecifiedZone");
      } else {
        Assertion::raise("A sender in normal heap has an UnspecifiedZone");
      }
    }

    // MethodContext's need to be inspected on every GC collection, young
    // and old. This is because we perform stores into the MethodContext's
    // stack without running the write barrier. So if the context is
    // in mature, we remember it.
    if(!ctx->young_object_p()) {
      mark.gc->object_memory->remember_object(ctx);
    }

    auto_mark(obj, mark);

    /* Now also mark the stack. Set elements after sp to nil to prevent
     * memory leak */
    int sp = ctx->calculate_sp();
    if(sp < 0) {
      for(size_t i = 0; i < ctx->stack_size; i++) {
        ctx->stack_put(i, Qnil);
      }
    } else {
      size_t usp = sp;
      for(size_t i = 0; i <= usp; i++) {
        Object* stack_obj = ctx->stack_at(i);
        if(!stack_obj) continue;
        Object* marked = mark.call(stack_obj);
        if(marked) {
          ctx->stack_put(i, marked);
          mark.just_set(ctx, marked);
        }
      }
      for(size_t i = usp+1; i < ctx->stack_size; i++) {
        ctx->stack_put(i, Qnil);
      }
    }
  }

  void MethodContext::Info::show(STATE, Object* self, int level) {
    MethodContext* ctx = as<MethodContext>(self);

    class_header(state, self);
    indent_attribute(++level, "name"); ctx->name()->show(state, level);
    indent_attribute(level, "sp");
    std::cout << ctx->calculate_sp() << "\n";

    indent_attribute(level, "ip");
    std::cout << ctx->ip << "\n";

    indent_attribute(level, "sender");
    if(ctx->sender()->nil_p()) {
      ctx->sender()->show(state, level);
    } else {
      if(ctx->sender()->klass()->nil_p()) {
        std::cout << "<stack context:" << (void*)ctx->sender() << ">\n";
      } else {
        class_info(state, ctx->sender(), true);
      }
    }
    indent_attribute(level, "home");
    if(ctx->home()->nil_p()) {
      ctx->home()->show(state, level);
    } else {
      class_info(state, ctx->home(), true);
    }
    indent_attribute(level, "self"); ctx->self()->show(state, level);
    indent_attribute(level, "cm"); ctx->cm()->show(state, level);
    indent_attribute(level, "module"); ctx->module()->show(state, level);
    indent_attribute(level, "block"); ctx->block()->show(state, level);
    close_body(level);
  }
}
<commit_msg>Revert "Sets elements after sp in the stack to nil to prevent memory leak."<commit_after>#include "builtin/block_environment.hpp"
#include "builtin/class.hpp"
#include "builtin/compiledmethod.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/lookuptable.hpp"
#include "builtin/tuple.hpp"

#include "gc_object_mark.hpp"
#include "objectmemory.hpp"

#include "vm/object_utils.hpp"

#include "builtin/contexts.hpp"
#include "builtin/nativemethodcontext.hpp"

#include <iostream>

namespace rubinius {

  void MethodContext::init(STATE) {
    GO(methctx).set(state->new_class("MethodContext", G(object)));
    G(methctx)->set_object_type(state, MethodContextType);

    GO(blokctx).set(state->new_class("BlockContext", G(methctx)));
    G(blokctx)->set_object_type(state, BlockContextType);
  }

  /* Initialize +ctx+'s fields */
  static inline void init_context(STATE, MethodContext* ctx, size_t stack) {
    ctx->StoresBytes = 1;
    ctx->ip = 0;
    ctx->native_ip = 0;
    ctx->current_unwind = 0;
    ctx->ivars(state, Qnil);

    // Do this here because it's possible for us to pass a context
    // around and it could leak out before the real sender is set.
    ctx->sender(state, (MethodContext*)Qnil);

    // Don't initialize any fields you KNOW are always set later
    // on before the ctx is used. We just waste precious time if we do.

    ctx->stack_size = stack;
    for(size_t i = 0; i < stack; i++) {
      ctx->stk[i] = Qnil;
    }

    ctx->js.stack = ctx->stk - 1;
    ctx->js.stack_top = (ctx->stk + stack - 1);
  }

  /* Find a context to use. Either use a cache or create one in the heap. */
  template <class T>
    static inline T* allocate(STATE, Class* cls, size_t stack_size) {
      T* ctx;

      ctx = reinterpret_cast<T*>(state->om->allocate_context(stack_size));
      if(ctx) {
        assert((uintptr_t)ctx + ctx->full_size < (uintptr_t)state->om->contexts.last);
        ctx->klass(state, (Class*)Qnil);
        ctx->obj_type = T::type;
      } else {
        // We're going to end up referencing a stack context from a heap
        // context, so we need to be sure all stack contexts stick around!
        state->om->clamp_contexts();
        ctx = state->new_struct<T>(cls, stack_size * sizeof(Object*));
      }

      init_context(state, ctx, stack_size);
      return ctx;
    }

  int MethodContext::line(STATE) {
    if(cm_->nil_p()) return -2;        // trampoline context
    if(cm_->lines()->nil_p()) return -3;

    for(size_t i = 0; i < cm_->lines()->num_fields(); i++) {
      Tuple* entry = as<Tuple>(cm_->lines()->at(state, i));

      Fixnum* start_ip = as<Fixnum>(entry->at(state, 0));
      Fixnum* end_ip   = as<Fixnum>(entry->at(state, 1));
      Fixnum* line     = as<Fixnum>(entry->at(state, 2));

      if(start_ip->to_native() <= ip && end_ip->to_native() >= ip)
        return line->to_native();
    }

    return -1;
  }

  void MethodContext::post_copy(MethodContext* old) {
    this->js.stack_top = this->stk + (this->stack_size - 1);
    this->position_stack(old->calculate_sp());
    if(this->obj_type == MethodContextType) {
      assert(this->home() == old->home());
    }
  }

  /* Attempt to recycle +this+ context into the context cache, based
   * on it's size. Returns true if the context was recycled, otherwise
   * false. */
  bool MethodContext::recycle(STATE) {
    if(zone != YoungObjectZone) return false;
    return state->om->deallocate_context(this);
  }

  /* Create a ContextCache object and install it in +state+ */
  void MethodContext::initialize_cache(STATE) {
  }

  /* Zero out the caches. */
  void MethodContext::reset_cache(STATE) {
    state->om->clamp_contexts();
  }

  /* Return a new +MethodContext+ object, which needs +stack_size fields
   * worth of stack.
   */
  MethodContext* MethodContext::create(STATE, size_t stack_size) {
    return allocate<MethodContext>(state, G(methctx), stack_size);
  }

  /* Generate a MethodContext for the provided receiver and CompiledMethod
   * The returned MethodContext is in an 'initial' state. The caller is
   * expected to SET any fields it needs to, e.g. +module+
   */
  MethodContext* MethodContext::create(STATE, Object* recv, CompiledMethod* meth) {
    size_t stack_size = meth->backend_method_->stack_size;

    MethodContext* ctx = state->om->allocate_context(stack_size);
    if(likely(ctx)) {
      ctx->klass_ = (Class*)Qnil;
      ctx->obj_type = MethodContextType;

      ctx->self_ = recv;
      ctx->cm_ = meth;
      ctx->home_ = ctx;

    } else {
      // We're going to end up referencing a stack context from a heap
      // context, so we need to be sure all stack contexts stick around!
      state->om->clamp_contexts();
      ctx = state->new_struct<MethodContext>(G(methctx), stack_size * sizeof(Object*));

      ctx->self(state, recv);
      ctx->cm(state, meth);
      ctx->home(state, ctx);
    }

    init_context(state, ctx, stack_size);

    ctx->vmm = meth->backend_method_;
    ctx->run = ctx->vmm->run;

    // nil out just where the locals are
    native_int locals = ctx->vmm->number_of_locals;

    ctx->position_stack(locals - 1);

    return ctx;
  }

  /* Called as the context_dup primitive
   */
  MethodContext* MethodContext::dup(STATE) {
    MethodContext* ctx = create(state, this->stack_size);

    /* This ctx is escaping into Ruby-land */
    ctx->reference(state);

    ctx->sender(state, this->sender());
    ctx->self(state, this->self());
    ctx->cm(state, this->cm());
    ctx->module(state, this->module());
    ctx->block(state, this->block());
    ctx->name(state, this->name());

    ctx->home(state, this->home());
    this->home()->reference(state); // so that the closure won't be deallocated.

    /* Set the obj_type because we get called
     * for both BlockContext and MethodContext
     */
    ctx->obj_type = this->obj_type;

    ctx->vmm = this->vmm;
    ctx->run = this->run;
    ctx->js = this->js;
    ctx->ip = this->ip;
    ctx->native_ip = this->native_ip;
    ctx->args = this->args;
    ctx->stack_size = this->stack_size;

    ctx->full_size = this->full_size;
    ctx->current_unwind = this->current_unwind;

    for(int i = 0; i < this->current_unwind; i++) {
      ctx->unwinds[i] = this->unwinds[i];
    }

    for(size_t i = 0; i < this->stack_size; i++) {
      ctx->stk[i] = this->stk[i];
    }

    ctx->js.stack_top = ctx->stk + (ctx->stack_size - 1);
    ctx->position_stack(this->calculate_sp());

    /* Stack Management procedures. Make sure that we don't
     * miss object stored into the stack of a context
     */
    if(ctx->zone == MatureObjectZone) {
      state->om->remember_object(ctx);
    }

    return ctx;
  }

  MethodContext* MethodContext::dup_chain(STATE) {

    LookupTable* map = LookupTable::create(state);

    MethodContext* ret = this->dup(state);

    for(MethodContext* ctx = ret; !ctx->sender()->nil_p(); ctx = ctx->sender()) {
      MethodContext* old_sender = ctx->sender();
      ctx->sender(state, old_sender->dup(state));
      if(old_sender->obj_type == MethodContextType) {
        map->store(state, old_sender, ctx->sender());
      }
    }

    for(MethodContext* ctx = ret; !ctx->sender()->nil_p(); ctx = ctx->sender()) {
      if(ctx->obj_type == BlockContextType) {
        BlockEnvironment* old_env = as<BlockContext>(ctx)->env();
        Object* new_env_home = map->aref(state, (old_env->home()));
        if(new_env_home->nil_p()) continue;
        BlockEnvironment* new_env = old_env->dup(state);
        new_env->home(state, as<MethodContext>(new_env_home));
        ctx->block(state, new_env);
      }
    }

    for(MethodContext* ctx = this; !ctx->sender()->nil_p(); ctx = ctx->sender()) {
      if(ctx->obj_type == MethodContextType) {
        map->remove(state, ctx);
      }
    }

    return ret;
  }

  /* Retrieve the BlockEnvironment from +this+ BlockContext. We reuse the
   * block field from MethodContext and use a type-safe cast. */
  BlockEnvironment* BlockContext::env() {
    return as<BlockEnvironment>(block());
  }

  /* Called as the block_context_env primitive
   */
  BlockEnvironment* BlockContext::env(STATE) {
    return this->env();
  }

  /* Lazy initialize fields that might have been left uninitialized
   * when +this+ was only used in the context cache. */
  void MethodContext::initialize_as_reference(STATE) {
    switch(obj_type) {
    case MethodContext::type:
      this->klass(state, G(methctx));
      break;
    case BlockContext::type:
      this->klass(state, G(blokctx));
      break;
    case NativeMethodContext::type:
      break;
    default:
      abort();
    }
  }

  /* Called when a context is referenced. Typically, this is via the push_context
   * opcode or MethodContext#sender. */
  void MethodContext::reference(STATE) {
    state->om->reference_context(this);
    initialize_as_reference(state);
  }

  /* Retrieve a field within the context, referenced by name. This
   * is used as a primitive. */
  Object* MethodContext::get_internal_data(STATE, Fixnum* type) {
    switch(type->to_native()) {
    case 1:
      return Fixnum::from(ip);
    case 2:
      return Fixnum::from(calculate_sp());
    case 3:
      if(native_ip == 0) {
        return Qnil;
      } else {
        return Integer::from(state, reinterpret_cast<uintptr_t>(native_ip));
      }
    }

    sassert(0 && "invalid index");
    return Qnil;
  }

  Array* MethodContext::locals(STATE) {
    int n = this->vmm->number_of_locals;
    Array* ary = Array::create(state, n);
    for(int i = 0; i < n; i++) {
      ary->set(state, i, this->get_local(i));
    }
    return ary;
  }

  /* Return a new +BlockContext+ object, which needs +stack_size+ fields
   * worth of stack. */
  BlockContext* BlockContext::create(STATE, size_t stack_size) {
    BlockContext* ctx = allocate<BlockContext>(state, G(blokctx), stack_size);

    ctx->block(state, Qnil);
    ctx->cm(state, reinterpret_cast<CompiledMethod*>(Qnil));
    ctx->home(state, reinterpret_cast<MethodContext*>(Qnil));
    ctx->module(state, reinterpret_cast<Module*>(Qnil));
    ctx->name(state, Qnil);
    ctx->self(state, Qnil);
    ctx->sender(state, reinterpret_cast<MethodContext*>(Qnil));

    return ctx;
  }

  void MethodContext::Info::mark(Object* obj, ObjectMark& mark) {
    MethodContext* ctx = as<MethodContext>(obj);

    // Detect a context on the special context stack and fix it up.
    if(ctx->klass_->nil_p()) {
      ctx->initialize_as_reference(state());
    }

    // FIXME this is to help detect an ellusive bug
    if(!ctx->sender()->nil_p() &&
        (ctx->sender()->zone == UnspecifiedZone ||
         !ctx->sender()->StoresBytes)) {
      MethodContext* s = ctx->sender();
      std::cout << "Corrupt context detected!\n";
      std::cout << "origin = " << obj << "\n";
      std::cout << "object = " << s << "\n";
      std::cout << "full_size = " << s->full_size << "\n";
      std::cout << "klass = " << s->klass_ << "\n";

      ObjectPosition pos = mark.gc->object_memory->validate_object(ctx->sender());
      if(pos == cContextStack) {
        Assertion::raise("A sender on the context stack has an UnspecifiedZone");
      } else if(pos == cUnknown){
        Assertion::raise("A sender in unknown memory has an UnspecifiedZone");
      } else {
        Assertion::raise("A sender in normal heap has an UnspecifiedZone");
      }
    }

    // MethodContext's need to be inspected on every GC collection, young
    // and old. This is because we perform stores into the MethodContext's
    // stack without running the write barrier. So if the context is
    // in mature, we remember it.
    if(!ctx->young_object_p()) {
      mark.gc->object_memory->remember_object(ctx);
    }

    auto_mark(obj, mark);

    /* Now also mark the stack */
    for(size_t i = 0; i < ctx->stack_size; i++) {
      Object* stack_obj = ctx->stack_at(i);
      if(!stack_obj) continue;
      Object* marked = mark.call(stack_obj);
      if(marked) {
        ctx->stack_put(i, marked);
        mark.just_set(ctx, marked);
      }
    }
  }

  void MethodContext::Info::show(STATE, Object* self, int level) {
    MethodContext* ctx = as<MethodContext>(self);

    class_header(state, self);
    indent_attribute(++level, "name"); ctx->name()->show(state, level);
    indent_attribute(level, "sp");
    std::cout << ctx->calculate_sp() << "\n";

    indent_attribute(level, "ip");
    std::cout << ctx->ip << "\n";

    indent_attribute(level, "sender");
    if(ctx->sender()->nil_p()) {
      ctx->sender()->show(state, level);
    } else {
      if(ctx->sender()->klass()->nil_p()) {
        std::cout << "<stack context:" << (void*)ctx->sender() << ">\n";
      } else {
        class_info(state, ctx->sender(), true);
      }
    }
    indent_attribute(level, "home");
    if(ctx->home()->nil_p()) {
      ctx->home()->show(state, level);
    } else {
      class_info(state, ctx->home(), true);
    }
    indent_attribute(level, "self"); ctx->self()->show(state, level);
    indent_attribute(level, "cm"); ctx->cm()->show(state, level);
    indent_attribute(level, "module"); ctx->module()->show(state, level);
    indent_attribute(level, "block"); ctx->block()->show(state, level);
    close_body(level);
  }
}
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// 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 "google/cloud/storage/client.h"
#include <functional>
#include <iostream>
#include <map>
#include <sstream>

namespace gcs = google::cloud::storage;

namespace {
struct Usage {
  std::string msg;
};

char const* ConsumeArg(int& argc, char* argv[]) {
  if (argc < 2) {
    return nullptr;
  }
  char const* result = argv[1];
  std::copy(argv + 2, argv + argc, argv + 1);
  argc--;
  return result;
}

std::string command_usage;

void PrintUsage(int argc, char* argv[], std::string const& msg) {
  std::string const cmd = argv[0];
  auto last_slash = std::string(cmd).find_last_of('/');
  auto program = cmd.substr(last_slash + 1);
  std::cerr << msg << "\nUsage: " << program << " <command> [arguments]\n\n"
            << "Commands:\n"
            << command_usage << std::endl;
}

void ListObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc < 3) {
    throw Usage{"list-object-acl <bucket-name> <object-name>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  //! [list object acl] [START storage_print_file_acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name) {
    std::cout << "ACLs for object=" << object_name << " in bucket "
              << bucket_name << std::endl;
    for (gcs::ObjectAccessControl const& acl :
         client.ListObjectAcl(bucket_name, object_name)) {
      std::cout << acl.role() << ":" << acl.entity() << std::endl;
    }
  }
  //! [list object acl] [END storage_print_file_acl]
  (std::move(client), bucket_name, object_name);
}

void CreateObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc < 5) {
    throw Usage{
        "create-object-acl <bucket-name> <object-name> <entity> <role>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  auto role = ConsumeArg(argc, argv);
  //! [create object acl] [START storage_create_file_acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity, std::string role) {
    gcs::ObjectAccessControl result =
        client.CreateObjectAcl(bucket_name, object_name, entity, role);
    std::cout << "Role " << result.role() << " granted to " << result.entity()
              << " on " << result.object() << "\n"
              << "Full attributes: " << result << std::endl;
  }
  //! [create object acl] [END storage_create_file_acl]
  (std::move(client), bucket_name, object_name, entity, role);
}

void DeleteObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc < 4) {
    throw Usage{"delete-object-acl <bucket-name> <object-name> <entity>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  //! [delete object acl] [START storage_delete_file_acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity) {
    client.DeleteObjectAcl(bucket_name, object_name, entity);
    std::cout << "Deleted ACL entry for " << entity << " in object "
              << object_name << " in bucket " << bucket_name << std::endl;
  }
  //! [delete object acl] [END storage_delete_file_acl]
  (std::move(client), bucket_name, object_name, entity);
}

void GetObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc < 4) {
    throw Usage{"get-object-acl <bucket-name> <object-name> <entity>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  //! [get object acl] [START storage_print_file_acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity) {
    gcs::ObjectAccessControl acl =
        client.GetObjectAcl(bucket_name, object_name, entity);
    std::cout << "ACL entry for " << entity << " in object " << object_name
              << " in bucket " << bucket_name << " is " << acl << std::endl;
  }
  //! [get object acl] [END storage_print_file_acl]
  (std::move(client), bucket_name, object_name, entity);
}

void UpdateObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc < 5) {
    throw Usage{
        "update-object-acl <bucket-name> <object-name> <entity> <role>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  auto role = ConsumeArg(argc, argv);
  //! [update object acl] [START storage_update_file_acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity, std::string role) {
    gcs::ObjectAccessControl current_acl =
        client.GetObjectAcl(bucket_name, object_name, entity);
    current_acl.set_role(role);
    gcs::ObjectAccessControl acl =
        client.UpdateObjectAcl(bucket_name, object_name, current_acl);
    std::cout << "ACL entry for " << entity << " in object " << object_name
              << " in bucket " << bucket_name << " is now " << acl << std::endl;
  }
  //! [update object acl] [END storage_update_file_acl]
  (std::move(client), bucket_name, object_name, entity, role);
}

void PatchObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc != 5) {
    throw Usage{"patch-object-acl <bucket-name> <object-name> <entity> <role>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  auto role = ConsumeArg(argc, argv);
  //! [patch object acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity, std::string role) {
    gcs::ObjectAccessControl original_acl =
        client.GetObjectAcl(bucket_name, object_name, entity);
    auto new_acl = original_acl;
    new_acl.set_role(role);
    gcs::ObjectAccessControl updated_acl =
        client.PatchObjectAcl(bucket_name, object_name, entity, original_acl,
                              new_acl, gcs::IfMatchEtag(original_acl.etag()));
    std::cout << "ACL entry for " << entity << " in object " << object_name
              << " in bucket " << bucket_name << " is now " << updated_acl
              << std::endl;
  }
  //! [patch object acl]
  (std::move(client), bucket_name, object_name, entity, role);
}

void PatchObjectAclNoRead(gcs::Client client, int& argc, char* argv[]) {
  if (argc != 5) {
    throw Usage{
        "patch-object-acl-no-read <bucket-name> <object-name> <entity> <role>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  auto role = ConsumeArg(argc, argv);
  //! [patch object acl no-read]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity, std::string role) {
    gcs::ObjectAccessControl acl = client.PatchObjectAcl(
        bucket_name, object_name, entity,
        gcs::ObjectAccessControlPatchBuilder().set_role(role));
    std::cout << "ACL entry for " << entity << " in object " << object_name
              << " in bucket " << bucket_name << " is now " << acl << std::endl;
  }
  //! [patch object acl no-read]
  (std::move(client), bucket_name, object_name, entity, role);
}

}  // anonymous namespace

int main(int argc, char* argv[]) try {
  // Create a client to communicate with Google Cloud Storage.
  gcs::Client client;

  // Build the list of commands and the usage string from that list.
  using CommandType = std::function<void(gcs::Client, int&, char* [])>;
  std::map<std::string, CommandType> commands = {
      {"list-object-acl", &ListObjectAcl},
      {"create-object-acl", &CreateObjectAcl},
      {"delete-object-acl", &DeleteObjectAcl},
      {"get-object-acl", &GetObjectAcl},
      {"update-object-acl", &UpdateObjectAcl},
      {"patch-object-acl", &PatchObjectAcl},
      {"patch-object-acl-no-read", &PatchObjectAclNoRead},
  };
  for (auto&& kv : commands) {
    try {
      int fake_argc = 1;
      kv.second(client, fake_argc, argv);
    } catch (Usage const& u) {
      command_usage += "    ";
      command_usage += u.msg;
      command_usage += "\n";
    }
  }

  if (argc < 2) {
    PrintUsage(argc, argv, "Missing command");
    return 1;
  }

  std::string const command = ConsumeArg(argc, argv);
  auto it = commands.find(command);
  if (commands.end() == it) {
    PrintUsage(argc, argv, "Unknown command: " + command);
    return 1;
  }

  // Call the command with that client.
  it->second(client, argc, argv);

  return 0;
} catch (Usage const& ex) {
  PrintUsage(argc, argv, ex.msg);
  return 1;
} catch (std::exception const& ex) {
  std::cerr << "Standard C++ exception raised: " << ex.what() << std::endl;
  return 1;
}
<commit_msg>Remove duplicate region tag storage_print_file_acl (#1172)<commit_after>// Copyright 2018 Google LLC
//
// 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 "google/cloud/storage/client.h"
#include <functional>
#include <iostream>
#include <map>
#include <sstream>

namespace gcs = google::cloud::storage;

namespace {
struct Usage {
  std::string msg;
};

char const* ConsumeArg(int& argc, char* argv[]) {
  if (argc < 2) {
    return nullptr;
  }
  char const* result = argv[1];
  std::copy(argv + 2, argv + argc, argv + 1);
  argc--;
  return result;
}

std::string command_usage;

void PrintUsage(int argc, char* argv[], std::string const& msg) {
  std::string const cmd = argv[0];
  auto last_slash = std::string(cmd).find_last_of('/');
  auto program = cmd.substr(last_slash + 1);
  std::cerr << msg << "\nUsage: " << program << " <command> [arguments]\n\n"
            << "Commands:\n"
            << command_usage << std::endl;
}

void ListObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc < 3) {
    throw Usage{"list-object-acl <bucket-name> <object-name>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  //! [list object acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name) {
    std::cout << "ACLs for object=" << object_name << " in bucket "
              << bucket_name << std::endl;
    for (gcs::ObjectAccessControl const& acl :
         client.ListObjectAcl(bucket_name, object_name)) {
      std::cout << acl.role() << ":" << acl.entity() << std::endl;
    }
  }
  //! [list object acl]
  (std::move(client), bucket_name, object_name);
}

void CreateObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc < 5) {
    throw Usage{
        "create-object-acl <bucket-name> <object-name> <entity> <role>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  auto role = ConsumeArg(argc, argv);
  //! [create object acl] [START storage_create_file_acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity, std::string role) {
    gcs::ObjectAccessControl result =
        client.CreateObjectAcl(bucket_name, object_name, entity, role);
    std::cout << "Role " << result.role() << " granted to " << result.entity()
              << " on " << result.object() << "\n"
              << "Full attributes: " << result << std::endl;
  }
  //! [create object acl] [END storage_create_file_acl]
  (std::move(client), bucket_name, object_name, entity, role);
}

void DeleteObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc < 4) {
    throw Usage{"delete-object-acl <bucket-name> <object-name> <entity>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  //! [delete object acl] [START storage_delete_file_acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity) {
    client.DeleteObjectAcl(bucket_name, object_name, entity);
    std::cout << "Deleted ACL entry for " << entity << " in object "
              << object_name << " in bucket " << bucket_name << std::endl;
  }
  //! [delete object acl] [END storage_delete_file_acl]
  (std::move(client), bucket_name, object_name, entity);
}

void GetObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc < 4) {
    throw Usage{"get-object-acl <bucket-name> <object-name> <entity>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  //! [get object acl] [START storage_print_file_acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity) {
    gcs::ObjectAccessControl acl =
        client.GetObjectAcl(bucket_name, object_name, entity);
    std::cout << "ACL entry for " << entity << " in object " << object_name
              << " in bucket " << bucket_name << " is " << acl << std::endl;
  }
  //! [get object acl] [END storage_print_file_acl]
  (std::move(client), bucket_name, object_name, entity);
}

void UpdateObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc < 5) {
    throw Usage{
        "update-object-acl <bucket-name> <object-name> <entity> <role>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  auto role = ConsumeArg(argc, argv);
  //! [update object acl] [START storage_update_file_acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity, std::string role) {
    gcs::ObjectAccessControl current_acl =
        client.GetObjectAcl(bucket_name, object_name, entity);
    current_acl.set_role(role);
    gcs::ObjectAccessControl acl =
        client.UpdateObjectAcl(bucket_name, object_name, current_acl);
    std::cout << "ACL entry for " << entity << " in object " << object_name
              << " in bucket " << bucket_name << " is now " << acl << std::endl;
  }
  //! [update object acl] [END storage_update_file_acl]
  (std::move(client), bucket_name, object_name, entity, role);
}

void PatchObjectAcl(gcs::Client client, int& argc, char* argv[]) {
  if (argc != 5) {
    throw Usage{"patch-object-acl <bucket-name> <object-name> <entity> <role>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  auto role = ConsumeArg(argc, argv);
  //! [patch object acl]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity, std::string role) {
    gcs::ObjectAccessControl original_acl =
        client.GetObjectAcl(bucket_name, object_name, entity);
    auto new_acl = original_acl;
    new_acl.set_role(role);
    gcs::ObjectAccessControl updated_acl =
        client.PatchObjectAcl(bucket_name, object_name, entity, original_acl,
                              new_acl, gcs::IfMatchEtag(original_acl.etag()));
    std::cout << "ACL entry for " << entity << " in object " << object_name
              << " in bucket " << bucket_name << " is now " << updated_acl
              << std::endl;
  }
  //! [patch object acl]
  (std::move(client), bucket_name, object_name, entity, role);
}

void PatchObjectAclNoRead(gcs::Client client, int& argc, char* argv[]) {
  if (argc != 5) {
    throw Usage{
        "patch-object-acl-no-read <bucket-name> <object-name> <entity> <role>"};
  }
  auto bucket_name = ConsumeArg(argc, argv);
  auto object_name = ConsumeArg(argc, argv);
  auto entity = ConsumeArg(argc, argv);
  auto role = ConsumeArg(argc, argv);
  //! [patch object acl no-read]
  namespace gcs = google::cloud::storage;
  [](gcs::Client client, std::string bucket_name, std::string object_name,
     std::string entity, std::string role) {
    gcs::ObjectAccessControl acl = client.PatchObjectAcl(
        bucket_name, object_name, entity,
        gcs::ObjectAccessControlPatchBuilder().set_role(role));
    std::cout << "ACL entry for " << entity << " in object " << object_name
              << " in bucket " << bucket_name << " is now " << acl << std::endl;
  }
  //! [patch object acl no-read]
  (std::move(client), bucket_name, object_name, entity, role);
}

}  // anonymous namespace

int main(int argc, char* argv[]) try {
  // Create a client to communicate with Google Cloud Storage.
  gcs::Client client;

  // Build the list of commands and the usage string from that list.
  using CommandType = std::function<void(gcs::Client, int&, char* [])>;
  std::map<std::string, CommandType> commands = {
      {"list-object-acl", &ListObjectAcl},
      {"create-object-acl", &CreateObjectAcl},
      {"delete-object-acl", &DeleteObjectAcl},
      {"get-object-acl", &GetObjectAcl},
      {"update-object-acl", &UpdateObjectAcl},
      {"patch-object-acl", &PatchObjectAcl},
      {"patch-object-acl-no-read", &PatchObjectAclNoRead},
  };
  for (auto&& kv : commands) {
    try {
      int fake_argc = 1;
      kv.second(client, fake_argc, argv);
    } catch (Usage const& u) {
      command_usage += "    ";
      command_usage += u.msg;
      command_usage += "\n";
    }
  }

  if (argc < 2) {
    PrintUsage(argc, argv, "Missing command");
    return 1;
  }

  std::string const command = ConsumeArg(argc, argv);
  auto it = commands.find(command);
  if (commands.end() == it) {
    PrintUsage(argc, argv, "Unknown command: " + command);
    return 1;
  }

  // Call the command with that client.
  it->second(client, argc, argv);

  return 0;
} catch (Usage const& ex) {
  PrintUsage(argc, argv, ex.msg);
  return 1;
} catch (std::exception const& ex) {
  std::cerr << "Standard C++ exception raised: " << ex.what() << std::endl;
  return 1;
}
<|endoftext|>


<commit_before>// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
//
// 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.
#ifndef IOX_UTILS_CXX_TYPED_UNIQUE_ID_HPP
#define IOX_UTILS_CXX_TYPED_UNIQUE_ID_HPP

#include "iceoryx_utils/cxx/newtype.hpp"

#include <atomic>
#include <cstdint>
#include <iostream>

namespace iox
{
namespace cxx
{
/// @brief Unique ID depending on type. If you would like to assign different
///         types consistent unique ids use this class. Every types gets its
///         own distinct set of ids starting with 0. If the types are the same the
///         ids are the same.
///
/// @code
///     struct MyClass {
///         // some members;
///         iox::cxx::TypedUniqueId<MyClass> id;
///     };
///
///     struct MySecondClass {
///         // some members;
///         iox::cxx::TypedUniqueId<MySecondClass> id;
///     };
//
///     std::vector<MyClass> myClassVector;
///     std::vector<MyClass> mySecondClassVector;
///
///     uint64_t AddClass() {
///         myClassVector.emplace_back();
///         return myClassVector.back().id.getID();
///     }
///
///     uint64_t AddSecondClass() {
///         mySecondClassVector.emplace_back();
///         // we use the uint64_t conversion
///         return mySecondClassVector.back().id;
///     }
///
///     void RemoveClass(const uint64_t id) {
///         auto iter = std::find_if(myClassVector.begin(), myClassVector.end(), [&](MyClass & c){ return c.id == id;});
///         if ( iter != myClassVector.end() ) myClassVector.erase(iter);
///     }
///
///     uint64_t id = AddClass();
///     RemoveClass(id);
///
///     // it can be that id == id2 since the id is unique per type
///     uint64_t id2 = AddSecondClass();
/// @endcode
template <typename T, uint16_t MajorOffset>
class TypedUniqueId : public NewType<uint64_t,
                                     newtype::ProtectedConstructByValueCopy,
                                     newtype::Comparable,
                                     newtype::Sortable,
                                     newtype::Convertable,
                                     newtype::CopyConstructable,
                                     newtype::MoveConstructable,
                                     newtype::CopyAssignable,
                                     newtype::MoveAssignable>
{
  public:
    using ThisType::ThisType;

    /// @brief the constructor creates an id which is greater than the
    ///         previous created id
    TypedUniqueId() noexcept;

  private:
    struct Id
    {
        Id(const uint64_t minor) noexcept;
        explicit operator uint64_t() const noexcept;
        uint64_t m_minor : 48;
        uint16_t m_major : 16;
    };
    static std::atomic<uint64_t> globalIDCounter; // = 0u
};

} // namespace cxx
} // namespace iox

#include "iceoryx_utils/internal/cxx/typed_unique_id.inl"

#endif
<commit_msg>iox-#25: updated docu<commit_after>// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
//
// 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.
#ifndef IOX_UTILS_CXX_TYPED_UNIQUE_ID_HPP
#define IOX_UTILS_CXX_TYPED_UNIQUE_ID_HPP

#include "iceoryx_utils/cxx/newtype.hpp"

#include <atomic>
#include <cstdint>
#include <iostream>

namespace iox
{
namespace cxx
{
/// @brief Unique ID depending on type. If you would like to assign different
///         types consistent unique ids use this class. Every types gets its
///         own distinct set of ids starting with 0. If the types are the same the
///         ids are the same.
///
/// @code
///     struct MyClass {
///         // some members;
///         iox::cxx::TypedUniqueId<MyClass, 0> id;
///     };
///
///     struct MySecondClass {
///         // some members;
///         iox::cxx::TypedUniqueId<MySecondClass, 0> id;
///     };
//
///     std::vector<MyClass> myClassVector;
///     std::vector<MyClass> mySecondClassVector;
///
///     uint64_t AddClass() {
///         myClassVector.emplace_back();
///         return myClassVector.back().id.getID();
///     }
///
///     uint64_t AddSecondClass() {
///         mySecondClassVector.emplace_back();
///         // we use the uint64_t conversion
///         return mySecondClassVector.back().id;
///     }
///
///     void RemoveClass(const uint64_t id) {
///         auto iter = std::find_if(myClassVector.begin(), myClassVector.end(), [&](MyClass & c){ return c.id == id;});
///         if ( iter != myClassVector.end() ) myClassVector.erase(iter);
///     }
///
///     uint64_t id = AddClass();
///     RemoveClass(id);
///
///     // it can be that id == id2 since the id is unique per type
///     uint64_t id2 = AddSecondClass();
/// @endcode
/// @param[in] T type for which the unique ids should be generated
/// @param[in] MajorOffset every unique id has internally a major offset of
///             16 bit which is constant for all types.
///
template <typename T, uint16_t MajorOffset>
class TypedUniqueId : public NewType<uint64_t,
                                     newtype::ProtectedConstructByValueCopy,
                                     newtype::Comparable,
                                     newtype::Sortable,
                                     newtype::Convertable,
                                     newtype::CopyConstructable,
                                     newtype::MoveConstructable,
                                     newtype::CopyAssignable,
                                     newtype::MoveAssignable>
{
  public:
    using ThisType::ThisType;

    /// @brief the constructor creates an id which is greater than the
    ///         previous created id
    TypedUniqueId() noexcept;

  private:
    struct Id
    {
        Id(const uint64_t minor) noexcept;
        explicit operator uint64_t() const noexcept;
        uint64_t m_minor : 48;
        uint16_t m_major : 16;
    };
    static std::atomic<uint64_t> globalIDCounter; // = 0u
};

} // namespace cxx
} // namespace iox

#include "iceoryx_utils/internal/cxx/typed_unique_id.inl"

#endif
<|endoftext|>


<commit_before>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file robust_feature_obsrv_model.hpp
 * \date August 2015
 * \author Jan Issac (jan.issac@gmail.com)
 */

#pragma once

#include <fl/util/meta.hpp>
#include <fl/util/traits.hpp>
#include <fl/util/types.hpp>
#include <fl/util/descriptor.hpp>
#include <fl/distribution/gaussian.hpp>
#include <fl/model/observation/interface/observation_density.hpp>
#include <fl/model/observation/interface/observation_function.hpp>

namespace fl
{

namespace internal
{

enum RobustFeatureDimension { RobustFeatureDimExt = 2 };

}

/**
 * \ingroup observation_models
 *
 * \brief Represents an observation function or model which takes an arbitrary
 *        observation model (one that implements an ObservationFunction & a
 *        an ObservationDensity) as an argument and maps it into a feature space
 *        used by the RobustGaussianFilter.
 */
template <typename ObsrvModel>
class RobustFeatureObsrvModel
    : public ObservationFunction<
                 /* Obsrv type of the size SizeOf<ObsrvModel::Obsrv> + 2 */
                 typename VariateOfSize<
                     JoinSizes<
                         SizeOf<typename ObsrvModel::Obsrv>::Value,
                         internal::RobustFeatureDimExt
                     >::Value
                 >::Type,
                 typename ObsrvModel::State,
                 typename ObsrvModel::Noise>,
      public Descriptor

{
private:
    typedef RobustFeatureObsrvModel<ObsrvModel> This;

public:
    typedef ObsrvModel EmbeddedObsrvModel;

    /**
     * \brief \a InputObsrv type which is the same as
     *        ObsrvModel::Obsrv. \a InputObsrv is mapped into the feature space.
     *        The resulting type is \a Obsrv.
     */
    typedef typename ObsrvModel::Obsrv InputObsrv;

    /**
     * \brief \a Obsrv (\f$y_t\f$) type which is a variate of the size
     *        SizeOf<InputObsrv> + 2. \a Obsrv reside in the feature space.
     */
    typedef typename VariateOfSize<
                         JoinSizes<
                             SizeOf<typename ObsrvModel::Obsrv>::Value,
                             internal::RobustFeatureDimExt
                         >::Value
                     >::Type Obsrv;

    /**
     * \brief \a State (\f$x_t\f$) type which is the same as ObsrvModel::State
     */
    typedef typename ObsrvModel::State State;

    /**
     * \brief \a Noise (\f$x_t\f$) type which is the same as ObsrvModel::Noise
     */
    typedef typename ObsrvModel::Noise Noise;

public:
    /**
     * \brief Constructs a robust feature observation model for the robust
     *        gaussian filter
     *
     * \param obsrv_model   Reference to the source observation model
     *
     * \note This model takes only a reference of to an existing lvalue of the
     *       source model
     */
    explicit RobustFeatureObsrvModel(ObsrvModel& obsrv_model)
        : obsrv_model_(obsrv_model),
          body_gaussian_(obsrv_model.obsrv_dimension())
    { }

    /**
     * \brief Overridable default destructor
     */
    virtual ~RobustFeatureObsrvModel() { }

    /**
     * \brief observation Returns a feature mapped observation
     */
    Obsrv observation(const State& state, const Noise& noise) const override
    {
        auto input_obsrv = obsrv_model_.observation(state, noise);
        Obsrv y = feature_obsrv(input_obsrv);
        return y; // RVO
    }

    /**
     * \brief Computes the robust feature given an input feature fron the
     *        source observation model
     */
    virtual Obsrv feature_obsrv(const InputObsrv& input_obsrv) const
    {
        auto y = Obsrv(obsrv_dimension());

        //! \todo BG changes
        if(!std::isfinite(input_obsrv(0)))
        {
            for(int i = 0; i < y.size(); i++)
            {
                y(i) = std::numeric_limits<Real>::infinity();
            }
            return y;
        }

        auto weight = obsrv_model_.weight_threshold();
        auto prob_y = body_gaussian_.probability(input_obsrv);
        auto prob_tail = obsrv_model_
                            .tail_model()
                            .probability(input_obsrv, mean_state_);

        auto normalizer = 1.0 / ((1.0 - weight) * prob_y + weight * prob_tail);

        if(weight == 0)
        {
            y(0) = 0.0;
            if (internal::RobustFeatureDimExt == 2) y(1) = 1.0;
            y.bottomRows(obsrv_model_.obsrv_dimension()) = input_obsrv;
        }
        else if( !std::isfinite(1.0 / (weight * prob_tail)) )
        {
            std::cout << "prob_tail is too small: " << prob_tail
                      << "    weight: " << weight
                      << "    input_obsrv: " << input_obsrv.transpose()
                      << "    normalizer: " << normalizer
                      << std::endl;
            exit(-1);
        }
        else if(std::isfinite(normalizer))
        {
            y(0) = weight * prob_tail;
            if (internal::RobustFeatureDimExt == 2) y(1) =
                                                    (1.0 - weight) *  prob_y;
            y.bottomRows(obsrv_model_.obsrv_dimension()) =
                                        (1.0 - weight) * prob_y * input_obsrv;
            y *= normalizer;
        }
        else // if the normalizer is not finite, we assume that the
        {
            std::cout << "normalizer in robust feature is not finite "
                      << "    weight: " << weight
                      << "    input_obsrv: " << input_obsrv.transpose()
                      << "    normalizer: " << normalizer
                      << std::endl;
            exit(-1);

        }

//        if(y(0) < 0.9)
//        {
//            std::cout << "feature: " << y.transpose()
//                      << "    weight: " << weight
//                      << "    input_obsrv: " << input_obsrv.transpose()
//                      << "    normalizer: " << normalizer
//                      << std::endl;

//            std::cout << "prob_y " << prob_y << "  prob_tail: " << prob_tail <<
//                         std::endl;
//        }

        return y;
    }

    /**
     * \brief Sets the feature function \a mean_state;
     * \param mean_state        \f$ \mu_x \f$
     *
     * \todo PAPER REF
     */
    virtual void mean_state(const State& mean_state)
    {
        mean_state_ = mean_state;
    }

    /**
     * \brief Sets the feature function body moments
     * \param body_gaussian     \f${\cal N}(y_t\mid \mu_{y}, \Sigma_{yy})\f$
     *
     * \todo PAPER REF
     */
    virtual void body_moments(
        const typename FirstMomentOf<InputObsrv>::Type& mean_obsrv,
        const typename SecondMomentOf<InputObsrv>::Type& cov_obsrv)
    {
        body_gaussian_.mean(mean_obsrv);
        body_gaussian_.covariance(cov_obsrv);
    }

    /**
     * \brief Returns the dimension of the \a Obsrv which is dim(\a Obsrv) + 2
     */
    int obsrv_dimension() const override
    {
        return obsrv_model_.obsrv_dimension() + internal::RobustFeatureDimExt;
    }

    int noise_dimension() const override
    {
        return obsrv_model_.noise_dimension();
    }

    int state_dimension() const override
    {
        return obsrv_model_.state_dimension();
    }

    ObsrvModel& embedded_obsrv_model()
    {
        return obsrv_model_;
    }

    const ObsrvModel& embedded_obsrv_model() const
    {
        return obsrv_model_;
    }

    virtual int id() const { return obsrv_model_.id(); }

    virtual void id(int new_id) { obsrv_model_.id(new_id); }

    virtual std::string name() const
    {
        return "RobustFeatureObsrvModel<"
                + this->list_arguments(embedded_obsrv_model().name())
                + ">";
    }

    virtual std::string description() const
    {
        return "Robust feature observation model with "
                + this->list_descriptions(embedded_obsrv_model().description());
    }

public:
    /** \cond internal */

    /**
     * \brief Reference to the ource observation model
     */
    ObsrvModel& obsrv_model_;

    /**
     * \brief \f${\cal N}(y_t\mid \mu_{y}, \Sigma_{yy})\f$
     */
    Gaussian<InputObsrv> body_gaussian_;

    /**
     * \brief \f$\mu_x\f$
     */
    State mean_state_;

    /* \endcond */
};

}

<commit_msg>:lipstick:<commit_after>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file robust_feature_obsrv_model.hpp
 * \date August 2015
 * \author Jan Issac (jan.issac@gmail.com)
 */

#pragma once

#include <fl/util/meta.hpp>
#include <fl/util/traits.hpp>
#include <fl/util/types.hpp>
#include <fl/util/descriptor.hpp>
#include <fl/distribution/gaussian.hpp>
#include <fl/model/observation/interface/observation_density.hpp>
#include <fl/model/observation/interface/observation_function.hpp>

namespace fl
{

namespace internal
{

enum RobustFeatureDimension { RobustFeatureDimExt = 2 };

}

/**
 * \ingroup observation_models
 *
 * \brief Represents an observation function or model which takes an arbitrary
 *        observation model (one that implements an ObservationFunction & a
 *        an ObservationDensity) as an argument and maps it into a feature space
 *        used by the RobustGaussianFilter.
 */
template <typename ObsrvModel>
class RobustFeatureObsrvModel
    : public ObservationFunction<
                 /* Obsrv type of the size SizeOf<ObsrvModel::Obsrv> + 2 */
                 typename VariateOfSize<
                     JoinSizes<
                         SizeOf<typename ObsrvModel::Obsrv>::Value,
                         internal::RobustFeatureDimExt
                     >::Value
                 >::Type,
                 typename ObsrvModel::State,
                 typename ObsrvModel::Noise>,
      public Descriptor

{
private:
    typedef RobustFeatureObsrvModel<ObsrvModel> This;

public:
    typedef ObsrvModel EmbeddedObsrvModel;

    /**
     * \brief \a InputObsrv type which is the same as
     *        ObsrvModel::Obsrv. \a InputObsrv is mapped into the feature space.
     *        The resulting type is \a Obsrv.
     */
    typedef typename ObsrvModel::Obsrv InputObsrv;

    /**
     * \brief \a Obsrv (\f$y_t\f$) type which is a variate of the size
     *        SizeOf<InputObsrv> + 2. \a Obsrv reside in the feature space.
     */
    typedef typename VariateOfSize<
                         JoinSizes<
                             SizeOf<typename ObsrvModel::Obsrv>::Value,
                             internal::RobustFeatureDimExt
                         >::Value
                     >::Type Obsrv;

    /**
     * \brief \a State (\f$x_t\f$) type which is the same as ObsrvModel::State
     */
    typedef typename ObsrvModel::State State;

    /**
     * \brief \a Noise (\f$x_t\f$) type which is the same as ObsrvModel::Noise
     */
    typedef typename ObsrvModel::Noise Noise;

public:
    /**
     * \brief Constructs a robust feature observation model for the robust
     *        gaussian filter
     *
     * \param obsrv_model   Reference to the source observation model
     *
     * \note This model takes only a reference of to an existing lvalue of the
     *       source model
     */
    explicit RobustFeatureObsrvModel(ObsrvModel& obsrv_model)
        : obsrv_model_(obsrv_model),
          body_gaussian_(obsrv_model.obsrv_dimension())
    { }

    /**
     * \brief Overridable default destructor
     */
    virtual ~RobustFeatureObsrvModel() { }

    /**
     * \brief observation Returns a feature mapped observation
     */
    Obsrv observation(const State& state, const Noise& noise) const override
    {
        auto input_obsrv = obsrv_model_.observation(state, noise);
        Obsrv y = feature_obsrv(input_obsrv);
        return y; // RVO
    }

    /**
     * \brief Computes the robust feature given an input feature fron the
     *        source observation model
     */
    virtual Obsrv feature_obsrv(const InputObsrv& input_obsrv) const
    {
        auto y = Obsrv(obsrv_dimension());

        //! \todo BG changes
        if(!std::isfinite(input_obsrv(0)))
        {
            for(int i = 0; i < y.size(); i++)
            {
                y(i) = std::numeric_limits<Real>::infinity();
            }
            return y;
        }

        auto weight = obsrv_model_.weight_threshold();
        auto prob_y = body_gaussian_.probability(input_obsrv);
        auto prob_tail = obsrv_model_
                            .tail_model()
                            .probability(input_obsrv, mean_state_);

        auto normalizer = 1.0 / ((1.0 - weight) * prob_y + weight * prob_tail);

        if(weight == 0)
        {
            y(0) = 0.0;
            if (internal::RobustFeatureDimExt == 2) y(1) = 1.0;
            y.bottomRows(obsrv_model_.obsrv_dimension()) = input_obsrv;
        }
        else if( !std::isfinite(1.0 / (weight * prob_tail)) )
        {
            std::cout << "prob_tail is too small: " << prob_tail
                      << "    weight: " << weight
                      << "    input_obsrv: " << input_obsrv.transpose()
                      << "    normalizer: " << normalizer
                      << std::endl;
            exit(-1);
        }
        else if(std::isfinite(normalizer))
        {
            y(0) = weight * prob_tail;
            if (internal::RobustFeatureDimExt == 2) y(1) =
                                                    (1.0 - weight) *  prob_y;
            y.bottomRows(obsrv_model_.obsrv_dimension()) =
                                        (1.0 - weight) * prob_y * input_obsrv;
            y *= normalizer;
        }
        else // if the normalizer is not finite, we assume that the
        {
            std::cout << "normalizer in robust feature is not finite "
                      << "    weight: " << weight
                      << "    input_obsrv: " << input_obsrv.transpose()
                      << "    normalizer: " << normalizer
                      << std::endl;
            exit(-1);

        }

        return y;
    }

    /**
     * \brief Sets the feature function \a mean_state;
     * \param mean_state        \f$ \mu_x \f$
     *
     * \todo PAPER REF
     */
    virtual void mean_state(const State& mean_state)
    {
        mean_state_ = mean_state;
    }

    /**
     * \brief Sets the feature function body moments
     * \param body_gaussian     \f${\cal N}(y_t\mid \mu_{y}, \Sigma_{yy})\f$
     *
     * \todo PAPER REF
     */
    virtual void body_moments(
        const typename FirstMomentOf<InputObsrv>::Type& mean_obsrv,
        const typename SecondMomentOf<InputObsrv>::Type& cov_obsrv)
    {
        body_gaussian_.mean(mean_obsrv);
        body_gaussian_.covariance(cov_obsrv);
    }

    /**
     * \brief Returns the dimension of the \a Obsrv which is dim(\a Obsrv) + 2
     */
    int obsrv_dimension() const override
    {
        return obsrv_model_.obsrv_dimension() + internal::RobustFeatureDimExt;
    }

    int noise_dimension() const override
    {
        return obsrv_model_.noise_dimension();
    }

    int state_dimension() const override
    {
        return obsrv_model_.state_dimension();
    }

    ObsrvModel& embedded_obsrv_model()
    {
        return obsrv_model_;
    }

    const ObsrvModel& embedded_obsrv_model() const
    {
        return obsrv_model_;
    }

    virtual int id() const { return obsrv_model_.id(); }

    virtual void id(int new_id) { obsrv_model_.id(new_id); }

    virtual std::string name() const
    {
        return "RobustFeatureObsrvModel<"
                + this->list_arguments(embedded_obsrv_model().name())
                + ">";
    }

    virtual std::string description() const
    {
        return "Robust feature observation model with "
                + this->list_descriptions(embedded_obsrv_model().description());
    }

public:
    /** \cond internal */

    /**
     * \brief Reference to the ource observation model
     */
    ObsrvModel& obsrv_model_;

    /**
     * \brief \f${\cal N}(y_t\mid \mu_{y}, \Sigma_{yy})\f$
     */
    Gaussian<InputObsrv> body_gaussian_;

    /**
     * \brief \f$\mu_x\f$
     */
    State mean_state_;

    /* \endcond */
};

}

<|endoftext|>


<commit_before>#include <common/CapricaReportingContext.h>

#include <cassert>
#include <iostream>

#include <common/CapricaConfig.h>

#include <Windows.h>

namespace caprica {

void CapricaReportingContext::pushToErrorStream(std::string&& msg, bool isError) {
  if (!conf::Performance::performanceTestMode || isError) {
    std::cout.flush();
    std::cerr << msg << std::endl;
  }
}

void CapricaReportingContext::breakIfDebugging() {
  if (IsDebuggerPresent()) {
    __debugbreak();
  }
}

void CapricaReportingContext::exitIfErrors() {
  if (errorCount > 0) {
    pushToErrorStream("Compilation of '" + filename + "' failed; " + std::to_string(warningCount) + " warnings and " + std::to_string(errorCount) + " errors were encountered.");
    throw std::runtime_error("");
  }
}

bool CapricaReportingContext::isWarningError(CapricaFileLocation location, size_t warningNumber) const {
  if (warningNumber >= 2000 && warningNumber <= 2200) {
    return !conf::EngineLimits::ignoreLimits && conf::Warnings::warningsToIgnore.count(warningNumber) == 0;
  }
  return conf::Warnings::treatWarningsAsErrors || conf::Warnings::warningsToHandleAsErrors.count(warningNumber);
}

bool CapricaReportingContext::isWarningEnabled(CapricaFileLocation location, size_t warningNumber) const {
  if (conf::Warnings::warningsToHandleAsErrors.count(warningNumber))
    return true;
  if (conf::Warnings::warningsToEnable.count(warningNumber))
    return true;
  if (conf::Warnings::warningsToIgnore.count(warningNumber))
    return false;
  if (warningNumber >= 2000 && warningNumber <= 2200)
    return !conf::EngineLimits::ignoreLimits;
  return !conf::Warnings::disableAllWarnings;
}

size_t CapricaReportingContext::getLocationLine(CapricaFileLocation location, size_t lastLineHint) const {
  if (!lineOffsets.size())
    CapricaReportingContext::logicalFatal("Unable to locate line at offset %zu.", location.fileOffset);
  if (lastLineHint != 0) {
    if (location.fileOffset >= lineOffsets[lastLineHint - 1]) {
      return lastLineHint + 1;
    }
    if (lastLineHint + 1 < lineOffsets.size()) {
      if (location.fileOffset >= lineOffsets[lastLineHint - 1]) {
        return lastLineHint + 1;
      }
    }
  }
  // TODO: B-Tree search.
  for (size_t i = lineOffsets.size() - 1; i >= 0; i--) {
    if (location.fileOffset >= lineOffsets[i]) {
      return i + 1;
    }
    if (i == 0)
      break;
  }
  CapricaReportingContext::logicalFatal("Unable to locate line at offset %zu.", location.fileOffset);
}

std::string CapricaReportingContext::formatLocation(CapricaFileLocation loc) const {
  std::string ret = filename + " (";
  auto line = getLocationLine(loc);
  ret += std::to_string(line) + ", ";
  ret += std::to_string(loc.fileOffset - lineOffsets[line - 1] + 1) + ")";
  return ret;
}

void CapricaReportingContext::maybePushMessage(CapricaReportingContext* ctx, CapricaFileLocation* location, const char* msgType, size_t warningNumber, const std::string& msg, bool forceAsError) {
  if (warningNumber != 0) {
    if (ctx->isWarningEnabled(*location, warningNumber)) {
      if (ctx->isWarningError(*location, warningNumber)) {
        ctx->errorCount++;
        pushToErrorStream(ctx->formatLocation(*location) + ": Error W" + std::to_string(warningNumber) + ": " + msg, true);
      } else {
        ctx->warningCount++;
        pushToErrorStream(ctx->formatLocation(*location) + ": Warning W" + std::to_string(warningNumber) + ": " + msg);
      }
    }
  } else if (location != nullptr) {
    pushToErrorStream(ctx->formatLocation(*location) + ": " + msgType + ": " + msg, forceAsError);
  } else {
    pushToErrorStream((std::string)msgType + ": " + msg, forceAsError);
  }
}

}
<commit_msg>Minor cleanup in the reporting context.<commit_after>#include <common/CapricaReportingContext.h>

#include <cassert>
#include <iostream>

#include <common/CapricaConfig.h>

#include <Windows.h>

namespace caprica {

void CapricaReportingContext::pushToErrorStream(std::string&& msg, bool isError) {
  if (!conf::Performance::performanceTestMode || isError) {
    std::cout.flush();
    std::cerr << msg << std::endl;
  }
}

void CapricaReportingContext::breakIfDebugging() {
  if (IsDebuggerPresent()) {
    __debugbreak();
  }
}

void CapricaReportingContext::exitIfErrors() {
  if (errorCount > 0) {
    pushToErrorStream("Compilation of '" + filename + "' failed; " + std::to_string(warningCount) + " warnings and " + std::to_string(errorCount) + " errors were encountered.");
    throw std::runtime_error("");
  }
}

bool CapricaReportingContext::isWarningError(CapricaFileLocation location, size_t warningNumber) const {
  if (warningNumber >= 2000 && warningNumber <= 2200) {
    return !conf::EngineLimits::ignoreLimits && conf::Warnings::warningsToIgnore.count(warningNumber) == 0;
  }
  return conf::Warnings::treatWarningsAsErrors || conf::Warnings::warningsToHandleAsErrors.count(warningNumber);
}

bool CapricaReportingContext::isWarningEnabled(CapricaFileLocation location, size_t warningNumber) const {
  if (conf::Warnings::warningsToHandleAsErrors.count(warningNumber))
    return true;
  if (conf::Warnings::warningsToEnable.count(warningNumber))
    return true;
  if (conf::Warnings::warningsToIgnore.count(warningNumber))
    return false;
  if (warningNumber >= 2000 && warningNumber <= 2200)
    return !conf::EngineLimits::ignoreLimits;
  return !conf::Warnings::disableAllWarnings;
}

size_t CapricaReportingContext::getLocationLine(CapricaFileLocation location, size_t lastLineHint) const {
  if (!lineOffsets.size())
    CapricaReportingContext::logicalFatal("Unable to locate line at offset %zu.", location.fileOffset);
  if (lastLineHint != 0) {
    if (location.fileOffset >= lineOffsets[lastLineHint - 1]) {
      return lastLineHint + 1;
    }
    if (lastLineHint + 1 < lineOffsets.size()) {
      if (location.fileOffset >= lineOffsets[lastLineHint - 1]) {
        return lastLineHint + 1;
      }
    }
  }
  // TODO: B-Tree search.
  for (size_t i = lineOffsets.size() - 1; i >= 0; i--) {
    if (location.fileOffset >= lineOffsets[i]) {
      return i + 1;
    }
    if (i == 0)
      break;
  }
  CapricaReportingContext::logicalFatal("Unable to locate line at offset %zu.", location.fileOffset);
}

std::string CapricaReportingContext::formatLocation(CapricaFileLocation loc) const {
  std::string ret = filename + " (";
  auto line = getLocationLine(loc);
  ret += std::to_string(line) + ", ";
  ret += std::to_string(loc.fileOffset - lineOffsets[line - 1] + 1) + ")";
  return ret;
}

void CapricaReportingContext::maybePushMessage(CapricaReportingContext* ctx, CapricaFileLocation* location, const char* msgType, size_t warningNumber, const std::string& msg, bool forceAsError) {
  if (warningNumber != 0) {
    if (ctx->isWarningEnabled(*location, warningNumber)) {
      if (ctx->isWarningError(*location, warningNumber)) {
        ctx->errorCount++;
        pushToErrorStream(ctx->formatLocation(*location) + ": Error W" + std::to_string(warningNumber) + ": " + msg, true);
      } else {
        ctx->warningCount++;
        pushToErrorStream(ctx->formatLocation(*location) + ": Warning W" + std::to_string(warningNumber) + ": " + msg);
      }
    }
  } else if (location != nullptr) {
    pushToErrorStream(ctx->formatLocation(*location) + ": " + msgType + ": " + msg, forceAsError);
  } else {
    pushToErrorStream(std::string(msgType) + ": " + msg, forceAsError);
  }
}

}
<|endoftext|>