<commit_before>/*
 * 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.
 *
 * Authors: Steve Reinhardt
 *          Nathan Binkert
 */

#ifndef __CPU_BASE_HH__
#define __CPU_BASE_HH__

#include <vector>

#include "arch/isa_traits.hh"
#include "arch/microcode_rom.hh"
#include "base/statistics.hh"
#include "config/full_system.hh"
#include "config/the_isa.hh"
#include "sim/eventq.hh"
#include "sim/insttracer.hh"
#include "mem/mem_object.hh"

#if FULL_SYSTEM
#include "arch/interrupts.hh"
#endif

class BaseCPUParams;
class BranchPred;
class CheckerCPU;
class ThreadContext;
class System;
class Port;

namespace TheISA
{
    class Predecoder;
}

class CPUProgressEvent : public Event
{
  protected:
    Tick _interval;
    Counter lastNumInst;
    BaseCPU *cpu;
    bool _repeatEvent;

  public:
    CPUProgressEvent(BaseCPU *_cpu, Tick ival = 0);

    void process();

    void interval(Tick ival) { _interval = ival; }
    Tick interval() { return _interval; }

    void repeatEvent(bool repeat) { _repeatEvent = repeat; }

    virtual const char *description() const;
};

class BaseCPU : public MemObject
{
  protected:
    // CPU's clock period in terms of the number of ticks of curTime.
    Tick clock;
    // @todo remove me after debugging with legion done
    Tick instCnt;
    // every cpu has an id, put it in the base cpu
    // Set at initialization, only time a cpuId might change is during a
    // takeover (which should be done from within the BaseCPU anyway,
    // therefore no setCpuId() method is provided
    int _cpuId;

  public:
    /** Reads this CPU's ID. */
    int cpuId() { return _cpuId; }

//    Tick currentTick;
    inline Tick frequency() const { return Clock::Frequency / clock; }
    inline Tick ticks(int numCycles) const { return clock * numCycles; }
    inline Tick curCycle() const { return curTick / clock; }
    inline Tick tickToCycles(Tick val) const { return val / clock; }
    // @todo remove me after debugging with legion done
    Tick instCount() { return instCnt; }

    /** The next cycle the CPU should be scheduled, given a cache
     * access or quiesce event returning on this cycle.  This function
     * may return curTick if the CPU should run on the current cycle.
     */
    Tick nextCycle();

    /** The next cycle the CPU should be scheduled, given a cache
     * access or quiesce event returning on the given Tick.  This
     * function may return curTick if the CPU should run on the
     * current cycle.
     * @param begin_tick The tick that the event is completing on.
     */
    Tick nextCycle(Tick begin_tick);

    TheISA::MicrocodeRom microcodeRom;

#if FULL_SYSTEM
  protected:
    TheISA::Interrupts *interrupts;

  public:
    TheISA::Interrupts *
    getInterruptController()
    {
        return interrupts;
    }

    virtual void wakeup() = 0;

    void
    postInterrupt(int int_num, int index)
    {
        interrupts->post(int_num, index);
        wakeup();
    }

    void
    clearInterrupt(int int_num, int index)
    {
        interrupts->clear(int_num, index);
    }

    void
    clearInterrupts()
    {
        interrupts->clearAll();
    }

    bool
    checkInterrupts(ThreadContext *tc) const
    {
        return interrupts->checkInterrupts(tc);
    }

    class ProfileEvent : public Event
    {
      private:
        BaseCPU *cpu;
        Tick interval;

      public:
        ProfileEvent(BaseCPU *cpu, Tick interval);
        void process();
    };
    ProfileEvent *profileEvent;
#endif

  protected:
    std::vector<ThreadContext *> threadContexts;
    std::vector<TheISA::Predecoder *> predecoders;

    Trace::InstTracer * tracer;

  public:

    /// Provide access to the tracer pointer
    Trace::InstTracer * getTracer() { return tracer; }

    /// Notify the CPU that the indicated context is now active.  The
    /// delay parameter indicates the number of ticks to wait before
    /// executing (typically 0 or 1).
    virtual void activateContext(int thread_num, int delay) {}

    /// Notify the CPU that the indicated context is now suspended.
    virtual void suspendContext(int thread_num) {}

    /// Notify the CPU that the indicated context is now deallocated.
    virtual void deallocateContext(int thread_num) {}

    /// Notify the CPU that the indicated context is now halted.
    virtual void haltContext(int thread_num) {}

   /// Given a Thread Context pointer return the thread num
   int findContext(ThreadContext *tc);

   /// Given a thread num get tho thread context for it
   ThreadContext *getContext(int tn) { return threadContexts[tn]; }

  public:
    typedef BaseCPUParams Params;
    const Params *params() const
    { return reinterpret_cast<const Params *>(_params); }
    BaseCPU(Params *params);
    virtual ~BaseCPU();

    virtual void init();
    virtual void startup();
    virtual void regStats();

    virtual void activateWhenReady(ThreadID tid) {};

    void registerThreadContexts();

    /// Prepare for another CPU to take over execution.  When it is
    /// is ready (drained pipe) it signals the sampler.
    virtual void switchOut();

    /// Take over execution from the given CPU.  Used for warm-up and
    /// sampling.
    virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc);

    /**
     *  Number of threads we're actually simulating (<= SMT_MAX_THREADS).
     * This is a constant for the duration of the simulation.
     */
    ThreadID numThreads;

    TheISA::CoreSpecific coreParams; //ISA-Specific Params That Set Up State in Core

    /**
     * Vector of per-thread instruction-based event queues.  Used for
     * scheduling events based on number of instructions committed by
     * a particular thread.
     */
    EventQueue **comInstEventQueue;

    /**
     * Vector of per-thread load-based event queues.  Used for
     * scheduling events based on number of loads committed by
     *a particular thread.
     */
    EventQueue **comLoadEventQueue;

    System *system;

    Tick phase;

#if FULL_SYSTEM
    /**
     * Serialize this object to the given output stream.
     * @param os The stream to serialize to.
     */
    virtual void serialize(std::ostream &os);

    /**
     * Reconstruct the state of this object from a checkpoint.
     * @param cp The checkpoint use.
     * @param section The section name of this object
     */
    virtual void unserialize(Checkpoint *cp, const std::string &section);

#endif

    /**
     * Return pointer to CPU's branch predictor (NULL if none).
     * @return Branch predictor pointer.
     */
    virtual BranchPred *getBranchPred() { return NULL; };

    virtual Counter totalInstructions() const { return 0; }

    // Function tracing
  private:
    bool functionTracingEnabled;
    std::ostream *functionTraceStream;
    Addr currentFunctionStart;
    Addr currentFunctionEnd;
    Tick functionEntryTick;
    void enableFunctionTrace();
    void traceFunctionsInternal(Addr pc);

  protected:
    void traceFunctions(Addr pc)
    {
        if (functionTracingEnabled)
            traceFunctionsInternal(pc);
    }

  private:
    static std::vector<BaseCPU *> cpuList;   //!< Static global cpu list

  public:
    static int numSimulatedCPUs() { return cpuList.size(); }
    static Counter numSimulatedInstructions()
    {
        Counter total = 0;

        int size = cpuList.size();
        for (int i = 0; i < size; ++i)
            total += cpuList[i]->totalInstructions();

        return total;
    }

  public:
    // Number of CPU cycles simulated
    Stats::Scalar numCycles;
};

#endif // __CPU_BASE_HH__
<commit_msg>since totalInstructions() is impl'ed by all the cpus, make it an abstract base class.<commit_after>/*
 * 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.
 *
 * Authors: Steve Reinhardt
 *          Nathan Binkert
 */

#ifndef __CPU_BASE_HH__
#define __CPU_BASE_HH__

#include <vector>

#include "arch/isa_traits.hh"
#include "arch/microcode_rom.hh"
#include "base/statistics.hh"
#include "config/full_system.hh"
#include "config/the_isa.hh"
#include "sim/eventq.hh"
#include "sim/insttracer.hh"
#include "mem/mem_object.hh"

#if FULL_SYSTEM
#include "arch/interrupts.hh"
#endif

class BaseCPUParams;
class BranchPred;
class CheckerCPU;
class ThreadContext;
class System;
class Port;

namespace TheISA
{
    class Predecoder;
}

class CPUProgressEvent : public Event
{
  protected:
    Tick _interval;
    Counter lastNumInst;
    BaseCPU *cpu;
    bool _repeatEvent;

  public:
    CPUProgressEvent(BaseCPU *_cpu, Tick ival = 0);

    void process();

    void interval(Tick ival) { _interval = ival; }
    Tick interval() { return _interval; }

    void repeatEvent(bool repeat) { _repeatEvent = repeat; }

    virtual const char *description() const;
};

class BaseCPU : public MemObject
{
  protected:
    // CPU's clock period in terms of the number of ticks of curTime.
    Tick clock;
    // @todo remove me after debugging with legion done
    Tick instCnt;
    // every cpu has an id, put it in the base cpu
    // Set at initialization, only time a cpuId might change is during a
    // takeover (which should be done from within the BaseCPU anyway,
    // therefore no setCpuId() method is provided
    int _cpuId;

  public:
    /** Reads this CPU's ID. */
    int cpuId() { return _cpuId; }

//    Tick currentTick;
    inline Tick frequency() const { return Clock::Frequency / clock; }
    inline Tick ticks(int numCycles) const { return clock * numCycles; }
    inline Tick curCycle() const { return curTick / clock; }
    inline Tick tickToCycles(Tick val) const { return val / clock; }
    // @todo remove me after debugging with legion done
    Tick instCount() { return instCnt; }

    /** The next cycle the CPU should be scheduled, given a cache
     * access or quiesce event returning on this cycle.  This function
     * may return curTick if the CPU should run on the current cycle.
     */
    Tick nextCycle();

    /** The next cycle the CPU should be scheduled, given a cache
     * access or quiesce event returning on the given Tick.  This
     * function may return curTick if the CPU should run on the
     * current cycle.
     * @param begin_tick The tick that the event is completing on.
     */
    Tick nextCycle(Tick begin_tick);

    TheISA::MicrocodeRom microcodeRom;

#if FULL_SYSTEM
  protected:
    TheISA::Interrupts *interrupts;

  public:
    TheISA::Interrupts *
    getInterruptController()
    {
        return interrupts;
    }

    virtual void wakeup() = 0;

    void
    postInterrupt(int int_num, int index)
    {
        interrupts->post(int_num, index);
        wakeup();
    }

    void
    clearInterrupt(int int_num, int index)
    {
        interrupts->clear(int_num, index);
    }

    void
    clearInterrupts()
    {
        interrupts->clearAll();
    }

    bool
    checkInterrupts(ThreadContext *tc) const
    {
        return interrupts->checkInterrupts(tc);
    }

    class ProfileEvent : public Event
    {
      private:
        BaseCPU *cpu;
        Tick interval;

      public:
        ProfileEvent(BaseCPU *cpu, Tick interval);
        void process();
    };
    ProfileEvent *profileEvent;
#endif

  protected:
    std::vector<ThreadContext *> threadContexts;
    std::vector<TheISA::Predecoder *> predecoders;

    Trace::InstTracer * tracer;

  public:

    /// Provide access to the tracer pointer
    Trace::InstTracer * getTracer() { return tracer; }

    /// Notify the CPU that the indicated context is now active.  The
    /// delay parameter indicates the number of ticks to wait before
    /// executing (typically 0 or 1).
    virtual void activateContext(int thread_num, int delay) {}

    /// Notify the CPU that the indicated context is now suspended.
    virtual void suspendContext(int thread_num) {}

    /// Notify the CPU that the indicated context is now deallocated.
    virtual void deallocateContext(int thread_num) {}

    /// Notify the CPU that the indicated context is now halted.
    virtual void haltContext(int thread_num) {}

   /// Given a Thread Context pointer return the thread num
   int findContext(ThreadContext *tc);

   /// Given a thread num get tho thread context for it
   ThreadContext *getContext(int tn) { return threadContexts[tn]; }

  public:
    typedef BaseCPUParams Params;
    const Params *params() const
    { return reinterpret_cast<const Params *>(_params); }
    BaseCPU(Params *params);
    virtual ~BaseCPU();

    virtual void init();
    virtual void startup();
    virtual void regStats();

    virtual void activateWhenReady(ThreadID tid) {};

    void registerThreadContexts();

    /// Prepare for another CPU to take over execution.  When it is
    /// is ready (drained pipe) it signals the sampler.
    virtual void switchOut();

    /// Take over execution from the given CPU.  Used for warm-up and
    /// sampling.
    virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc);

    /**
     *  Number of threads we're actually simulating (<= SMT_MAX_THREADS).
     * This is a constant for the duration of the simulation.
     */
    ThreadID numThreads;

    TheISA::CoreSpecific coreParams; //ISA-Specific Params That Set Up State in Core

    /**
     * Vector of per-thread instruction-based event queues.  Used for
     * scheduling events based on number of instructions committed by
     * a particular thread.
     */
    EventQueue **comInstEventQueue;

    /**
     * Vector of per-thread load-based event queues.  Used for
     * scheduling events based on number of loads committed by
     *a particular thread.
     */
    EventQueue **comLoadEventQueue;

    System *system;

    Tick phase;

#if FULL_SYSTEM
    /**
     * Serialize this object to the given output stream.
     * @param os The stream to serialize to.
     */
    virtual void serialize(std::ostream &os);

    /**
     * Reconstruct the state of this object from a checkpoint.
     * @param cp The checkpoint use.
     * @param section The section name of this object
     */
    virtual void unserialize(Checkpoint *cp, const std::string &section);

#endif

    /**
     * Return pointer to CPU's branch predictor (NULL if none).
     * @return Branch predictor pointer.
     */
    virtual BranchPred *getBranchPred() { return NULL; };

    virtual Counter totalInstructions() const = 0;

    // Function tracing
  private:
    bool functionTracingEnabled;
    std::ostream *functionTraceStream;
    Addr currentFunctionStart;
    Addr currentFunctionEnd;
    Tick functionEntryTick;
    void enableFunctionTrace();
    void traceFunctionsInternal(Addr pc);

  protected:
    void traceFunctions(Addr pc)
    {
        if (functionTracingEnabled)
            traceFunctionsInternal(pc);
    }

  private:
    static std::vector<BaseCPU *> cpuList;   //!< Static global cpu list

  public:
    static int numSimulatedCPUs() { return cpuList.size(); }
    static Counter numSimulatedInstructions()
    {
        Counter total = 0;

        int size = cpuList.size();
        for (int i = 0; i < size; ++i)
            total += cpuList[i]->totalInstructions();

        return total;
    }

  public:
    // Number of CPU cycles simulated
    Stats::Scalar numCycles;
};

#endif // __CPU_BASE_HH__
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <folly/portability/Constexpr.h>

#include <folly/portability/GTest.h>

using folly::constexpr_strcmp;
using folly::constexpr_strlen;
using folly::detail::constexpr_strcmp_fallback;
using folly::detail::constexpr_strlen_fallback;

template <typename, typename>
struct static_assert_same;
template <typename T>
struct static_assert_same<T, T> {};

TEST(ConstexprTest, constexpr_strlen_cstr) {
  constexpr auto v = "hello";
  {
    constexpr auto a = constexpr_strlen(v);
    void(static_assert_same<const size_t, decltype(a)>{});
    EXPECT_EQ(5, a);
  }
  {
    constexpr auto a = constexpr_strlen_fallback(v);
    void(static_assert_same<const size_t, decltype(a)>{});
    EXPECT_EQ(5, a);
  }
}

TEST(ConstexprTest, constexpr_strlen_ints) {
  constexpr int v[] = {5, 3, 4, 0, 7};
  {
    constexpr auto a = constexpr_strlen(v);
    void(static_assert_same<const size_t, decltype(a)>{});
    EXPECT_EQ(3, a);
  }
  {
    constexpr auto a = constexpr_strlen_fallback(v);
    void(static_assert_same<const size_t, decltype(a)>{});
    EXPECT_EQ(3, a);
  }
}

TEST(ConstexprTest, constexpr_strcmp_ints) {
  constexpr int v[] = {5, 3, 4, 0, 7};
  constexpr int v1[] = {6, 4};
  static_assert(constexpr_strcmp(v1, v) > 0, "constexpr_strcmp is broken");
  static_assert(constexpr_strcmp(v, v) == 0, "constexpr_strcmp is broken");
  static_assert(
      constexpr_strcmp_fallback(v1, v) > 0, "constexpr_strcmp is broken");
  static_assert(
      constexpr_strcmp_fallback(v, v) == 0, "constexpr_strcmp is broken");
}

static_assert(
    constexpr_strcmp("abc", "abc") == 0,
    "constexpr_strcmp is broken");
static_assert(constexpr_strcmp("", "") == 0, "constexpr_strcmp is broken");
static_assert(constexpr_strcmp("abc", "def") < 0, "constexpr_strcmp is broken");
static_assert(constexpr_strcmp("xyz", "abc") > 0, "constexpr_strcmp is broken");
static_assert(constexpr_strcmp("a", "abc") < 0, "constexpr_strcmp is broken");
static_assert(constexpr_strcmp("abc", "a") > 0, "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("abc", "abc") == 0,
    "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("", "") == 0,
    "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("abc", "def") < 0,
    "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("xyz", "abc") > 0,
    "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("a", "abc") < 0,
    "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("abc", "a") > 0,
    "constexpr_strcmp is broken");
<commit_msg>Add missing < 0 tests for constexpr_strcmp<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <folly/portability/Constexpr.h>

#include <folly/portability/GTest.h>

using folly::constexpr_strcmp;
using folly::constexpr_strlen;
using folly::detail::constexpr_strcmp_fallback;
using folly::detail::constexpr_strlen_fallback;

template <typename, typename>
struct static_assert_same;
template <typename T>
struct static_assert_same<T, T> {};

TEST(ConstexprTest, constexpr_strlen_cstr) {
  constexpr auto v = "hello";
  {
    constexpr auto a = constexpr_strlen(v);
    void(static_assert_same<const size_t, decltype(a)>{});
    EXPECT_EQ(5, a);
  }
  {
    constexpr auto a = constexpr_strlen_fallback(v);
    void(static_assert_same<const size_t, decltype(a)>{});
    EXPECT_EQ(5, a);
  }
}

TEST(ConstexprTest, constexpr_strlen_ints) {
  constexpr int v[] = {5, 3, 4, 0, 7};
  {
    constexpr auto a = constexpr_strlen(v);
    void(static_assert_same<const size_t, decltype(a)>{});
    EXPECT_EQ(3, a);
  }
  {
    constexpr auto a = constexpr_strlen_fallback(v);
    void(static_assert_same<const size_t, decltype(a)>{});
    EXPECT_EQ(3, a);
  }
}

TEST(ConstexprTest, constexpr_strcmp_ints) {
  constexpr int v[] = {5, 3, 4, 0, 7};
  constexpr int v1[] = {6, 4};
  static_assert(constexpr_strcmp(v1, v) > 0, "constexpr_strcmp is broken");
  static_assert(constexpr_strcmp(v, v1) < 0, "constexpr_strcmp is broken");
  static_assert(constexpr_strcmp(v, v) == 0, "constexpr_strcmp is broken");
  static_assert(
      constexpr_strcmp_fallback(v1, v) > 0, "constexpr_strcmp is broken");
  static_assert(
      constexpr_strcmp_fallback(v, v1) < 0, "constexpr_strcmp is broken");
  static_assert(
      constexpr_strcmp_fallback(v, v) == 0, "constexpr_strcmp is broken");
}

static_assert(
    constexpr_strcmp("abc", "abc") == 0,
    "constexpr_strcmp is broken");
static_assert(constexpr_strcmp("", "") == 0, "constexpr_strcmp is broken");
static_assert(constexpr_strcmp("abc", "def") < 0, "constexpr_strcmp is broken");
static_assert(constexpr_strcmp("xyz", "abc") > 0, "constexpr_strcmp is broken");
static_assert(constexpr_strcmp("a", "abc") < 0, "constexpr_strcmp is broken");
static_assert(constexpr_strcmp("abc", "a") > 0, "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("abc", "abc") == 0,
    "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("", "") == 0,
    "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("abc", "def") < 0,
    "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("xyz", "abc") > 0,
    "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("a", "abc") < 0,
    "constexpr_strcmp is broken");
static_assert(
    constexpr_strcmp_fallback("abc", "a") > 0,
    "constexpr_strcmp is broken");
<|endoftext|>


<commit_before>#include <Empathy/Empathy/Empathy.h>
#include <Empathy/empathy-linear/linear_empathy.h>
#include <irrKlang.h>
#include <GLFW/glfw3.h>
#include <muParser.h>
#include <Empathy/Brain/CustomLogic/Calming_1.h>

#define FULL_SCREEN false

#if FULL_SCREEN
 #define RENDER_SIZE 768
 #define SC_SIZE_X 1366
 #define SC_SIZE_Y 768
#else
 #define RENDER_SIZE 690
 #define SC_SIZE_X 700
 #define SC_SIZE_Y 700
#endif

using namespace std;

static GLFWwindow * window;
static GLfloat mouseX,mouseY;
irrklang::ISoundEngine* engine;
static GLdouble lastPressTime;
static GLdouble thresholdTime=0.2;
static GLboolean mousePressed=GL_FALSE;

void createClickEvent(int button=GLFW_MOUSE_BUTTON_LEFT){
    empathy::radio::Event event(EMPATHY_EVENT_ACTION_NONE);

    if(button==GLFW_MOUSE_BUTTON_LEFT ){
        event=empathy::radio::Event(EMPATHY_EVENT_INPUT_MOUSE_LEFT_KEY_PRESS);
    }else if(button==GLFW_MOUSE_BUTTON_RIGHT){
        event=empathy::radio::Event(EMPATHY_EVENT_INPUT_MOUSE_RIGHT_KEY_PRESS);
    }

    event.putDouble(EMPATHY_MOUSE_XPOS,mouseX);
    event.putDouble(EMPATHY_MOUSE_YPOS,RENDER_SIZE-mouseY);

    empathy::radio::BroadcastStation::emit(event);
}

void mouse_input_callback(GLFWwindow *window, int button, int action, int mods) {
    if(action==GLFW_PRESS){
        createClickEvent(button);

        lastPressTime=glfwGetTime();

        mousePressed=GL_TRUE;

    }else if(action==GLFW_RELEASE){
        lastPressTime=0;
        mousePressed=GL_FALSE;
    }
}

void character_callback(GLFWwindow* window, unsigned int codepoint){

    std::string myAction=EMPATHY_EVENT_INPUT_KEY_PRESS;

    empathy::radio::Event event(myAction);
    event.putInt(EMPATHY_EVENT_INPUT_KEY, codepoint);

    empathy::radio::BroadcastStation::emit(event);
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {
//    std::cout<<"key call back received"<<action<<std::endl;

    // When a user presses the escape key, we set the WindowShouldClose property to true,
    // closing the application

    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
//        glfwSetWindowShouldClose(instance->window, GL_TRUE);
        empathy_linear::makeReadyToClose();

        return;
    }

    if(key == GLFW_KEY_ENTER){
        empathy::radio::Event event(EMPATHY_EVENT_INPUT_KEY_PRESS);
        event.putInt(EMPATHY_EVENT_INPUT_KEY,key);

        empathy::radio::BroadcastStation::emit(event);
    }

}

void mouse_position_callback(GLFWwindow *window, double xpos, double ypos) {

    mouseX= xpos -(SC_SIZE_X-RENDER_SIZE)/2;;

    mouseY = ypos - (SC_SIZE_Y-RENDER_SIZE)/2;
}

void initGlfw() {
    //	cout<<"glfwInit"<<endl;

    glfwInit();

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    //Create a GLFW window
    window = glfwCreateWindow((GLuint)SC_SIZE_X, (GLuint)SC_SIZE_Y, "Empathy | <3",
                              FULL_SCREEN ? glfwGetPrimaryMonitor(): nullptr, nullptr);
    if (window == nullptr)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glfwMakeContextCurrent(window);

    glfwSetCharCallback(window, character_callback);

    //set event receiver call backs.
    glfwSetKeyCallback(window, key_callback);
    glfwSetMouseButtonCallback(window,mouse_input_callback);
    glfwSetCursorPosCallback(window,mouse_position_callback);
}

void init(){
    initGlfw();
    empathy_linear::init();
    empathy_linear::setScreenMargins( (SC_SIZE_X-RENDER_SIZE)/2 , (SC_SIZE_Y-RENDER_SIZE)/2);

    empathy_linear::setScreenSize(RENDER_SIZE);

//    empathy_linear::addJsonBrain("brains/Calming_1.json");
	empathy_linear::addBrain(new empathy::brain::Calming_1());
//    empathy_linear::addJsonBrain("brains/CanonInD.json");
//    empathy_linear::addEmotionBrain();

    empathy_linear::addDummyTouchBrain();

    engine = irrklang::createIrrKlangDevice();

    if (!engine)
    {
        printf("Could not startup engine\n");
        exit(EXIT_FAILURE);
    }

    engine->setSoundVolume(0.4f);
}

void loop(){
    while(! empathy_linear::shouldClose() && !glfwWindowShouldClose(window)){

        std::stack<empathy::moonlight::BasicNote> audioEvents= empathy_linear::getMusicalKeyboardEvents();

        while(! audioEvents.empty()){
            empathy::moonlight::BasicNote playableItem=audioEvents.top();

            std::string fileName=playableItem.getNote();
            fileName += playableItem.getOctave()<=1?"":std::to_string(playableItem.getOctave()-1);
            if(playableItem.isSharp()){
                fileName="#"+fileName;

            }

            std::string path=empathy::getAssetPath("audio/keyboard/music/"+fileName+".mp3");

            try{
//                cout<<"Playing audio "<<fileName<<endl;

                engine->play2D(path.c_str());
            }catch (int i){
                cout<<"Could not play "<<path<<endl;
                continue;
            }

            audioEvents.pop();
        }

        if(mousePressed && glfwGetTime()-lastPressTime>thresholdTime){
            createClickEvent();
        }

        glfwPollEvents();

        empathy_linear::loop();

        empathy_linear::setTime((GLfloat ) glfwGetTime());

        glfwSwapBuffers(window);
    }
}

void flush(){
    engine->drop();

    empathy_linear::flush();

    if(window!= nullptr)
        glfwSetWindowShouldClose(window,true);

    glfwTerminate();
}

int  main() {
    init();
    loop();
    flush();
}
<commit_msg>Input bug with backspace and key repetition fixed.<commit_after>#include <Empathy/Empathy/Empathy.h>
#include <Empathy/empathy-linear/linear_empathy.h>
#include <irrKlang.h>
#include <GLFW/glfw3.h>
#include <muParser.h>
#include <Empathy/Brain/CustomLogic/Calming_1.h>

#define FULL_SCREEN false

#if FULL_SCREEN
 #define RENDER_SIZE 768
 #define SC_SIZE_X 1366
 #define SC_SIZE_Y 768
#else
 #define RENDER_SIZE 690
 #define SC_SIZE_X 700
 #define SC_SIZE_Y 700
#endif

using namespace std;

static GLFWwindow * window;
static GLfloat mouseX,mouseY;
irrklang::ISoundEngine* engine;
static GLdouble lastPressTime;
static GLdouble thresholdTime=0.2;
static GLboolean mousePressed=GL_FALSE;

void createClickEvent(int button=GLFW_MOUSE_BUTTON_LEFT){
    empathy::radio::Event event(EMPATHY_EVENT_ACTION_NONE);

    if(button==GLFW_MOUSE_BUTTON_LEFT ){
        event=empathy::radio::Event(EMPATHY_EVENT_INPUT_MOUSE_LEFT_KEY_PRESS);
    }else if(button==GLFW_MOUSE_BUTTON_RIGHT){
        event=empathy::radio::Event(EMPATHY_EVENT_INPUT_MOUSE_RIGHT_KEY_PRESS);
    }

    event.putDouble(EMPATHY_MOUSE_XPOS,mouseX);
    event.putDouble(EMPATHY_MOUSE_YPOS,RENDER_SIZE-mouseY);

    empathy::radio::BroadcastStation::emit(event);
}

void mouse_input_callback(GLFWwindow *window, int button, int action, int mods) {
    if(action==GLFW_PRESS){
        createClickEvent(button);

        lastPressTime=glfwGetTime();

        mousePressed=GL_TRUE;

    }else if(action==GLFW_RELEASE){
        lastPressTime=0;
        mousePressed=GL_FALSE;
    }
}

void character_callback(GLFWwindow* window, unsigned int codepoint){

    std::string myAction=EMPATHY_EVENT_INPUT_KEY_PRESS;

    empathy::radio::Event event(myAction);
    event.putInt(EMPATHY_EVENT_INPUT_KEY, codepoint);

    empathy::radio::BroadcastStation::emit(event);
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {

    // When a user presses the escape key, we set the WindowShouldClose property to true,
    // closing the application
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
//        glfwSetWindowShouldClose(instance->window, GL_TRUE);
        empathy_linear::makeReadyToClose();

        return;
    }
    else if(action == GLFW_PRESS || action == GLFW_REPEAT ) {
        if (key == GLFW_KEY_ENTER) {
            empathy::radio::Event event(EMPATHY_EVENT_INPUT_KEY_PRESS);
            event.putInt(EMPATHY_EVENT_INPUT_KEY, key);
            empathy::radio::BroadcastStation::emit(event);
        }
        else if (key == GLFW_KEY_BACKSPACE) {
            empathy::radio::Event event(EMPATHY_EVENT_INPUT_KEY_PRESS);
            event.putInt(EMPATHY_EVENT_INPUT_KEY, key);
            empathy::radio::BroadcastStation::emit(event);
        }
    }
}

void mouse_position_callback(GLFWwindow *window, double xpos, double ypos) {

    mouseX= xpos -(SC_SIZE_X-RENDER_SIZE)/2;;

    mouseY = ypos - (SC_SIZE_Y-RENDER_SIZE)/2;
}

void initGlfw() {
    //	cout<<"glfwInit"<<endl;

    glfwInit();

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    //Create a GLFW window
    window = glfwCreateWindow((GLuint)SC_SIZE_X, (GLuint)SC_SIZE_Y, "Empathy | <3",
                              FULL_SCREEN ? glfwGetPrimaryMonitor(): nullptr, nullptr);
    if (window == nullptr)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glfwMakeContextCurrent(window);

    glfwSetCharCallback(window, character_callback);

    //set event receiver call backs.
    glfwSetKeyCallback(window, key_callback);
    glfwSetMouseButtonCallback(window,mouse_input_callback);
    glfwSetCursorPosCallback(window,mouse_position_callback);
}

void init(){
    initGlfw();
    empathy_linear::init();
    empathy_linear::setScreenMargins( (SC_SIZE_X-RENDER_SIZE)/2 , (SC_SIZE_Y-RENDER_SIZE)/2);

    empathy_linear::setScreenSize(RENDER_SIZE);

//    empathy_linear::addJsonBrain("brains/Calming_1.json");
	empathy_linear::addBrain(new empathy::brain::Calming_1());
//    empathy_linear::addJsonBrain("brains/CanonInD.json");
//    empathy_linear::addEmotionBrain();

    empathy_linear::addDummyTouchBrain();

    engine = irrklang::createIrrKlangDevice();

    if (!engine)
    {
        printf("Could not startup engine\n");
        exit(EXIT_FAILURE);
    }

    engine->setSoundVolume(0.4f);
}

void loop(){
    while(! empathy_linear::shouldClose() && !glfwWindowShouldClose(window)){

        std::stack<empathy::moonlight::BasicNote> audioEvents= empathy_linear::getMusicalKeyboardEvents();

        while(! audioEvents.empty()){
            empathy::moonlight::BasicNote playableItem=audioEvents.top();

            std::string fileName=playableItem.getNote();
            fileName += playableItem.getOctave()<=1?"":std::to_string(playableItem.getOctave()-1);
            if(playableItem.isSharp()){
                fileName="#"+fileName;

            }

            std::string path=empathy::getAssetPath("audio/keyboard/music/"+fileName+".mp3");

            try{
//                cout<<"Playing audio "<<fileName<<endl;

                engine->play2D(path.c_str());
            }catch (int i){
                cout<<"Could not play "<<path<<endl;
                continue;
            }

            audioEvents.pop();
        }

        if(mousePressed && glfwGetTime()-lastPressTime>thresholdTime){
            createClickEvent();
        }

        glfwPollEvents();

        empathy_linear::loop();

        empathy_linear::setTime((GLfloat ) glfwGetTime());

        glfwSwapBuffers(window);
    }
}

void flush(){
    engine->drop();

    empathy_linear::flush();

    if(window!= nullptr)
        glfwSetWindowShouldClose(window,true);

    glfwTerminate();
}

int  main() {
    init();
    loop();
    flush();
}
<|endoftext|>


<commit_before>// This file is part of the dune-grid-multiscale project:
//   http://users.dune-project.org/projects/dune-grid-multiscale
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GRID_MULTISCALE_PROVIDER_CUBE_HH
#define DUNE_GRID_MULTISCALE_PROVIDER_CUBE_HH

#include <vector>
#include <memory>
#include <type_traits>

#include <dune/common/exceptions.hh>

#include <dune/grid/common/mcmgmapper.hh>
#include <dune/grid/io/file/vtk/vtkwriter.hh>
#include <dune/grid/io/file/dgfparser.hh>
#if HAVE_ALUGRID
#include <dune/grid/alugrid.hh>
#endif

#include <dune/stuff/grid/provider/cube.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/print.hh>
#include <dune/stuff/common/memory.hh>
#include <dune/stuff/common/type_utils.hh>

#include <dune/grid/multiscale/factory/default.hh>

#include "interface.hh"

namespace Dune {
namespace grid {
namespace Multiscale {
namespace Providers {

#if HAVE_DUNE_FEM

template <class GridImp>
class Cube : public ProviderInterface<GridImp>
{
  typedef ProviderInterface<GridImp> BaseType;
  typedef Cube<GridImp> ThisType;

public:
  typedef typename BaseType::GridType GridType;
  typedef typename BaseType::MsGridType MsGridType;

  static const unsigned int dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainType DomainType;

  static std::string static_id() { return BaseType::static_id() + ".cube"; }

  static Stuff::Common::Configuration default_config(const std::string sub_name = "")
  {
    Stuff::Common::Configuration config;
    config["type"]                = static_id();
    config["lower_left"]          = "[0.0 0.0 0.0]";
    config["upper_right"]         = "[1.0 1.0 1.0]";
    config["num_elements"]        = "[8 8 8]";
    config["num_partitions"]      = "[2 2 2]";
    config["oversampling_layers"] = "0";
    if (sub_name.empty())
      return config;
    else {
      Stuff::Common::Configuration tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... createSampleDescription(...)

  static std::unique_ptr<ThisType> create(const Stuff::Common::Configuration config = default_config(),
                                          const std::string sub_name = static_id())
  {
    // get correct config
    const Stuff::Common::Configuration cfg         = config.has_sub(sub_name) ? config.sub(sub_name) : config;
    const Stuff::Common::Configuration default_cfg = default_config();
    return Stuff::Common::make_unique<ThisType>(
        cfg.get("lower_left", default_cfg.get<DomainType>("lower_left"), dimDomain),
        cfg.get("upper_right", default_cfg.get<DomainType>("upper_right"), dimDomain),
        cfg.get("num_elements", default_cfg.get<std::vector<unsigned int>>("num_elements"), dimDomain),
        cfg.get("num_partitions", default_cfg.get<std::vector<size_t>>("num_partitions"), dimDomain),
        cfg.get("oversampling_layers", default_cfg.get<size_t>("oversampling_layers")));
  } // ... create(...)

  Cube(const DomainType lower_left = default_config().template get<DomainType>("lower_left"),
       const DomainType upper_right                 = default_config().template get<DomainType>("upper_right"),
       const std::vector<unsigned int> num_elements = default_config().template get<std::vector<unsigned int>>("num_elements"),
       const std::vector<size_t> num_partittions = default_config().template get<std::vector<size_t>>("num_partitions",
                                                                                dimDomain),
       const size_t num_oversampling_layers = default_config().template get<size_t>("oversampling_layers"),
       std::ostream& out = DSC_LOG.devnull(), const std::string prefix = "")
  {
    if (num_partittions.size() < dimDomain)
      DUNE_THROW(Dune::RangeError,
                 "num_partittions has to be at least of size " << dimDomain << " (is " << num_partittions.size()
                                                               << ")!");
#ifndef DUNE_GRID_MULTISCALE_PROVIDER_CUBE_DISABLE_CHECKS
    for (size_t ii = 0; ii < dimDomain; ++ii) {
      if (num_partittions[ii] > num_elements[ii])
        DUNE_THROW(Dune::RangeError,
                   num_partittions[ii] << " = num_partittions[" << ii << "] has to be smaller than "
                                       << "num_elements["
                                       << ii
                                       << "] = "
                                       << num_elements[ii]
                                       << "!)");
    }
#endif // DUNE_GRID_MULTISCALE_PROVIDER_CUBE_DISABLE_CHECKS
    typedef Dune::Stuff::Grid::Providers::Cube<GridType> CubeGridProvider;
    auto grd_ptr = CubeGridProvider(lower_left, upper_right, num_elements).grid_ptr();
#if HAVE_ALUGRID
    if (std::is_same<GridType, ALUGrid<2, 2, simplex, conforming>>::value)
      grd_ptr->globalRefine(1);
#endif
    grid_ = grd_ptr;
    setup(lower_left, upper_right, num_partittions, num_oversampling_layers, out, prefix);
  }

  Cube(const std::shared_ptr<const GridType> grd,
       const DomainType lower_left               = default_config().template get<DomainType>("lower_left"),
       const DomainType upper_right              = default_config().template get<DomainType>("upper_right"),
       const std::vector<size_t> num_partittions = default_config().template get<std::vector<size_t>>("num_partitions",
                                                                                dimDomain),
       const size_t num_oversampling_layers = default_config().template get<size_t>("oversampling_layers"),
       std::ostream& out = DSC_LOG.devnull(), const std::string prefix = "")
    : grid_(grd)
  {
    if (num_partittions.size() < dimDomain)
      DUNE_THROW(Dune::RangeError,
                 "num_partittions has to be at least of size " << dimDomain << " (is " << num_partittions.size()
                                                               << ")!");
    for (size_t ii = 0; ii < dimDomain; ++ii) {
      if (lower_left[ii] >= upper_right[ii])
        DUNE_THROW(Dune::RangeError,
                   lower_left[ii] << " = lower_left[" << ii << "] has to be smaller than upper_right[" << ii << "] = "
                                  << upper_right[ii]
                                  << "!)");
    }
    setup(lower_left, upper_right, num_partittions, num_oversampling_layers, out, prefix);
  }

  virtual const GridType& grid() const override { return *grid_; }

  virtual const std::shared_ptr<const MsGridType>& ms_grid() const override { return ms_grid_; }

  std::shared_ptr<const GridType> grid_ptr() const { return grid_; }

  virtual std::unique_ptr<Stuff::Grid::ConstProviderInterface<GridType>> copy() const
  {
    DUNE_THROW(NotImplemented, "");
  }

private:
  void setup(const DomainType& lower_left, const DomainType& upper_right, const std::vector<size_t>& num_partitions,
             const size_t num_oversampling_layers, std::ostream& out = DSC_LOG.devnull(), const std::string prefix = "")
  {
    typedef Dune::grid::Multiscale::Factory::Default<GridType> MsGridFactoryType;

    const size_t neighbor_recursion_level = Factory::NeighborRecursionLevel<GridType>::compute();
    // prepare
    MsGridFactoryType factory(grid_);
    factory.prepare();
#ifndef NDEBUG
    // debug output
    out << prefix << static_id() << ":" << std::endl;
    Stuff::Common::print(lower_left, "lower_left", out, prefix);
    Stuff::Common::print(upper_right, "upper_right", out, prefix);
    Stuff::Common::print(num_partitions, "num_partitions", out, prefix);
#endif // NDEBUG
    // global grid part
    typedef typename MsGridType::GlobalGridPartType GridPartType;
    const auto global_grid_part = factory.globalGridPart();
    // walk the grid
    const auto entity_it_end = global_grid_part->template end<0>();
    for (auto entity_it = global_grid_part->template begin<0>(); entity_it != entity_it_end; ++entity_it) {
      // get center of entity
      const auto& entity = *entity_it;
      const auto center  = entity.geometry().center();
#ifndef NDEBUG
      const size_t entity_index = global_grid_part->indexSet().index(entity);
      Stuff::Common::print(center, "entity (" + Stuff::Common::toString(entity_index) + ")", out, prefix);
#endif // NDEBUG
      // decide on the subdomain this entity shall belong to
      std::vector<size_t> whichPartition(dimDomain, 0);
      for (size_t dd = 0; dd < dimDomain; ++dd)
        whichPartition[dd] =
            (std::min((size_t)(std::floor(num_partitions[dd]
                                          * ((center[dd] - lower_left[dd]) / (upper_right[dd] - lower_left[dd])))),
                      num_partitions[dd] - 1));
      size_t subdomain = 0;
      if (dimDomain == 1)
        subdomain = whichPartition[0];
      else if (dimDomain == 2)
        subdomain = whichPartition[0] + whichPartition[1] * num_partitions[0];
      else if (dimDomain == 3)
        subdomain = whichPartition[0] + whichPartition[1] * num_partitions[0]
                    + whichPartition[2] * num_partitions[1] * num_partitions[0];
      else
        DUNE_THROW(Dune::NotImplemented,
                   "ERROR in " << static_id() << ": not implemented for grid dimDomains other than 1, 2 or 3!");
      // add entity to subdomain
      factory.add(entity, subdomain, prefix + "  ", out);
    } // walk the grid
    // finalize
    factory.finalize(num_oversampling_layers, neighbor_recursion_level, prefix + "  ", out);
    //    debug << std::flush;
    // be done with it
    ms_grid_ = factory.createMsGrid();
  } // void setup(const Dune::ParameterTree& paramTree)

  std::shared_ptr<const GridType> grid_;
  std::shared_ptr<const MsGridType> ms_grid_;
}; // class Cube

#else // HAVE_DUNE_FEM

template <class GridImp>
class Cube
{
  static_assert(AlwaysFalse<GridImp>::value, "Your are missing dune-fem!");
};

#endif // HAVE_DUNE_FEM

} // namespace Providers
} // namespace Multiscale
} // namespace Grid
} // namespace Dune

#endif // DUNE_GRID_MULTISCALE_PROVIDER_CUBE_HH
<commit_msg>[provider.cube] silence<commit_after>// This file is part of the dune-grid-multiscale project:
//   http://users.dune-project.org/projects/dune-grid-multiscale
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GRID_MULTISCALE_PROVIDER_CUBE_HH
#define DUNE_GRID_MULTISCALE_PROVIDER_CUBE_HH

#include <vector>
#include <memory>
#include <type_traits>

#include <dune/common/exceptions.hh>

#include <dune/grid/common/mcmgmapper.hh>
#include <dune/grid/io/file/vtk/vtkwriter.hh>
#include <dune/grid/io/file/dgfparser.hh>
#if HAVE_ALUGRID
#include <dune/grid/alugrid.hh>
#endif

#include <dune/stuff/grid/provider/cube.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/print.hh>
#include <dune/stuff/common/memory.hh>
#include <dune/stuff/common/type_utils.hh>

#include <dune/grid/multiscale/factory/default.hh>

#include "interface.hh"

namespace Dune {
namespace grid {
namespace Multiscale {
namespace Providers {

#if HAVE_DUNE_FEM

template <class GridImp>
class Cube : public ProviderInterface<GridImp>
{
  typedef ProviderInterface<GridImp> BaseType;
  typedef Cube<GridImp> ThisType;

public:
  typedef typename BaseType::GridType GridType;
  typedef typename BaseType::MsGridType MsGridType;

  static const unsigned int dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainType DomainType;

  static std::string static_id() { return BaseType::static_id() + ".cube"; }

  static Stuff::Common::Configuration default_config(const std::string sub_name = "")
  {
    Stuff::Common::Configuration config;
    config["type"]                = static_id();
    config["lower_left"]          = "[0.0 0.0 0.0]";
    config["upper_right"]         = "[1.0 1.0 1.0]";
    config["num_elements"]        = "[8 8 8]";
    config["num_partitions"]      = "[2 2 2]";
    config["oversampling_layers"] = "0";
    if (sub_name.empty())
      return config;
    else {
      Stuff::Common::Configuration tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... createSampleDescription(...)

  static std::unique_ptr<ThisType> create(const Stuff::Common::Configuration config = default_config(),
                                          const std::string sub_name = static_id())
  {
    // get correct config
    const Stuff::Common::Configuration cfg         = config.has_sub(sub_name) ? config.sub(sub_name) : config;
    const Stuff::Common::Configuration default_cfg = default_config();
    return Stuff::Common::make_unique<ThisType>(
        cfg.get("lower_left", default_cfg.get<DomainType>("lower_left"), dimDomain),
        cfg.get("upper_right", default_cfg.get<DomainType>("upper_right"), dimDomain),
        cfg.get("num_elements", default_cfg.get<std::vector<unsigned int>>("num_elements"), dimDomain),
        cfg.get("num_partitions", default_cfg.get<std::vector<size_t>>("num_partitions"), dimDomain),
        cfg.get("oversampling_layers", default_cfg.get<size_t>("oversampling_layers")));
  } // ... create(...)

  Cube(const DomainType lower_left = default_config().template get<DomainType>("lower_left"),
       const DomainType upper_right                 = default_config().template get<DomainType>("upper_right"),
       const std::vector<unsigned int> num_elements = default_config().template get<std::vector<unsigned int>>("num_elements"),
       const std::vector<size_t> num_partittions = default_config().template get<std::vector<size_t>>("num_partitions",
                                                                                dimDomain),
       const size_t num_oversampling_layers = default_config().template get<size_t>("oversampling_layers")/*,
       std::ostream& out = DSC_LOG.devnull(), const std::string prefix = ""*/)
  {
    if (num_partittions.size() < dimDomain)
      DUNE_THROW(Dune::RangeError,
                 "num_partittions has to be at least of size " << dimDomain << " (is " << num_partittions.size()
                                                               << ")!");
#ifndef DUNE_GRID_MULTISCALE_PROVIDER_CUBE_DISABLE_CHECKS
    for (size_t ii = 0; ii < dimDomain; ++ii) {
      if (num_partittions[ii] > num_elements[ii])
        DUNE_THROW(Dune::RangeError,
                   num_partittions[ii] << " = num_partittions[" << ii << "] has to be smaller than "
                                       << "num_elements["
                                       << ii
                                       << "] = "
                                       << num_elements[ii]
                                       << "!)");
    }
#endif // DUNE_GRID_MULTISCALE_PROVIDER_CUBE_DISABLE_CHECKS
    typedef Dune::Stuff::Grid::Providers::Cube<GridType> CubeGridProvider;
    auto grd_ptr = CubeGridProvider(lower_left, upper_right, num_elements).grid_ptr();
#if HAVE_ALUGRID
    if (std::is_same<GridType, ALUGrid<2, 2, simplex, conforming>>::value)
      grd_ptr->globalRefine(1);
#endif
    grid_ = grd_ptr;
    setup(lower_left, upper_right, num_partittions, num_oversampling_layers/*, out, prefix*/);
  }

  Cube(const std::shared_ptr<const GridType> grd,
       const DomainType lower_left               = default_config().template get<DomainType>("lower_left"),
       const DomainType upper_right              = default_config().template get<DomainType>("upper_right"),
       const std::vector<size_t> num_partittions = default_config().template get<std::vector<size_t>>("num_partitions",
                                                                                dimDomain),
       const size_t num_oversampling_layers = default_config().template get<size_t>("oversampling_layers")/*,
       std::ostream& out = DSC_LOG.devnull(), const std::string prefix = ""*/)
    : grid_(grd)
  {
    if (num_partittions.size() < dimDomain)
      DUNE_THROW(Dune::RangeError,
                 "num_partittions has to be at least of size " << dimDomain << " (is " << num_partittions.size()
                                                               << ")!");
    for (size_t ii = 0; ii < dimDomain; ++ii) {
      if (lower_left[ii] >= upper_right[ii])
        DUNE_THROW(Dune::RangeError,
                   lower_left[ii] << " = lower_left[" << ii << "] has to be smaller than upper_right[" << ii << "] = "
                                  << upper_right[ii]
                                  << "!)");
    }
    setup(lower_left, upper_right, num_partittions, num_oversampling_layers/*, out, prefix*/);
  }

  virtual const GridType& grid() const override { return *grid_; }

  virtual const std::shared_ptr<const MsGridType>& ms_grid() const override { return ms_grid_; }

  std::shared_ptr<const GridType> grid_ptr() const { return grid_; }

  virtual std::unique_ptr<Stuff::Grid::ConstProviderInterface<GridType>> copy() const
  {
    DUNE_THROW(NotImplemented, "");
  }

private:
  void setup(const DomainType& lower_left, const DomainType& upper_right, const std::vector<size_t>& num_partitions,
             const size_t num_oversampling_layers/*, std::ostream& out = DSC_LOG.devnull(), const std::string prefix = ""*/)
  {
    typedef Dune::grid::Multiscale::Factory::Default<GridType> MsGridFactoryType;

    const size_t neighbor_recursion_level = Factory::NeighborRecursionLevel<GridType>::compute();
    // prepare
    MsGridFactoryType factory(grid_);
    factory.prepare();
//#ifndef NDEBUG
//    // debug output
//    out << prefix << static_id() << ":" << std::endl;
//    Stuff::Common::print(lower_left, "lower_left", out, prefix);
//    Stuff::Common::print(upper_right, "upper_right", out, prefix);
//    Stuff::Common::print(num_partitions, "num_partitions", out, prefix);
//#endif // NDEBUG
    // global grid part
    typedef typename MsGridType::GlobalGridPartType GridPartType;
    const auto global_grid_part = factory.globalGridPart();
    // walk the grid
    const auto entity_it_end = global_grid_part->template end<0>();
    for (auto entity_it = global_grid_part->template begin<0>(); entity_it != entity_it_end; ++entity_it) {
      // get center of entity
      const auto& entity = *entity_it;
      const auto center  = entity.geometry().center();
//#ifndef NDEBUG
//      const size_t entity_index = global_grid_part->indexSet().index(entity);
//      Stuff::Common::print(center, "entity (" + Stuff::Common::toString(entity_index) + ")", out, prefix);
//#endif // NDEBUG
      // decide on the subdomain this entity shall belong to
      std::vector<size_t> whichPartition(dimDomain, 0);
      for (size_t dd = 0; dd < dimDomain; ++dd)
        whichPartition[dd] =
            (std::min((size_t)(std::floor(num_partitions[dd]
                                          * ((center[dd] - lower_left[dd]) / (upper_right[dd] - lower_left[dd])))),
                      num_partitions[dd] - 1));
      size_t subdomain = 0;
      if (dimDomain == 1)
        subdomain = whichPartition[0];
      else if (dimDomain == 2)
        subdomain = whichPartition[0] + whichPartition[1] * num_partitions[0];
      else if (dimDomain == 3)
        subdomain = whichPartition[0] + whichPartition[1] * num_partitions[0]
                    + whichPartition[2] * num_partitions[1] * num_partitions[0];
      else
        DUNE_THROW(Dune::NotImplemented,
                   "ERROR in " << static_id() << ": not implemented for grid dimDomains other than 1, 2 or 3!");
      // add entity to subdomain
      factory.add(entity, subdomain/*, prefix + "  ", out*/);
    } // walk the grid
    // finalize
    factory.finalize(num_oversampling_layers, neighbor_recursion_level/*, prefix + "  ", out*/);
    //    debug << std::flush;
    // be done with it
    ms_grid_ = factory.createMsGrid();
  } // void setup(const Dune::ParameterTree& paramTree)

  std::shared_ptr<const GridType> grid_;
  std::shared_ptr<const MsGridType> ms_grid_;
}; // class Cube

#else // HAVE_DUNE_FEM

template <class GridImp>
class Cube
{
  static_assert(AlwaysFalse<GridImp>::value, "Your are missing dune-fem!");
};

#endif // HAVE_DUNE_FEM

} // namespace Providers
} // namespace Multiscale
} // namespace Grid
} // namespace Dune

#endif // DUNE_GRID_MULTISCALE_PROVIDER_CUBE_HH
<|endoftext|>


<commit_before>/*
  Copyright (c) 2019-2020 Carsten Burstedde, Donna Calhoun, Scott Aiton, Grady Wright
  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.

  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 HOLDER 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.
*/

#include <ThunderEgg/Vector.h>

// #include <fclaw2d_global.h>

/* Avoid circular dependencies */
struct fclaw2d_patch;
struct fclaw2d_domain;
struct fclaw2d_global;

typedef enum fc2d_thunderegg_data_choice
{
    RHS=0,
    SOLN,
    STORE_STATE,
}  fc2d_thunderegg_data_choice_t;

/**
 * @brief Get a thunderegg vector that is a view to forestclaw data
 *
 * @param glob the global context
 * @param data_choice the data choice
 * @return ThunderEgg::Vector<2> the vector
 */
ThunderEgg::Vector<2> fc2d_thunderegg_get_vector(struct fclaw2d_global *glob, fc2d_thunderegg_data_choice_t data_choice);

/**
 * @brief Get a thunderegg vector that is a view to forestclaw data
 *
 * @param glob the global context
 * @param data_choice the data choice
 * @return ThunderEgg::Vector<2> the vector
 */
void fc2d_thunderegg_store_vector(struct fclaw2d_global *glob, fc2d_thunderegg_data_choice_t data_choice, const ThunderEgg::Vector<2>& vec);

<commit_msg>filled in documentation<commit_after>/*
  Copyright (c) 2019-2021 Carsten Burstedde, Donna Calhoun, Scott Aiton, Grady Wright
  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.

  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 HOLDER 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.
*/

/**
 * @file
 * Routines for interfaceing with ThunderEgg vectors
 */

#include <ThunderEgg/Vector.h>

/* Avoid circular dependencies */
struct fclaw2d_patch;
struct fclaw2d_domain;
struct fclaw2d_global;

/**
 * @brief Choice for patch data
 */
typedef enum fc2d_thunderegg_data_choice
{
    /** @brief RHS patch data */
    RHS=0,
    /** @brief soln patch data */
    SOLN,
    /** @brief soln patch data */
    STORE_STATE,
}  fc2d_thunderegg_data_choice_t;

/**
 * @brief Get a thunderegg vector that is a view to forestclaw data
 *
 * @param glob the global context
 * @param data_choice the data choice
 * @return ThunderEgg::Vector<2> the vector
 */
ThunderEgg::Vector<2> fc2d_thunderegg_get_vector(struct fclaw2d_global *glob, fc2d_thunderegg_data_choice_t data_choice);

/**
 * @brief Get a thunderegg vector that is a view to forestclaw data
 *
 * @param glob the global context
 * @param data_choice the data choice
 * @return ThunderEgg::Vector<2> the vector
 */
void fc2d_thunderegg_store_vector(struct fclaw2d_global *glob, fc2d_thunderegg_data_choice_t data_choice, const ThunderEgg::Vector<2>& vec);

<|endoftext|>


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

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

#include <stdio.h>

#include "saldisp.hxx"
#include "saldata.hxx"

#ifndef _SAL_I18N_XKBDEXTENSION_HXX
#include "i18n_xkb.hxx"
#endif

SalI18N_KeyboardExtension::SalI18N_KeyboardExtension( Display*
#if __XKeyboardExtension__
pDisplay
#endif
)
    : mbUseExtension( (sal_Bool)__XKeyboardExtension__ ),
      mnDefaultGroup( 0 )
{
    #if __XKeyboardExtension__

    mpDisplay = pDisplay;

    // allow user to set the default keyboard group idx or to disable the usage
    // of x keyboard extension at all:
    //      setenv SAL_XKEYBOARDGROUP       disables keyboard extension
    //      setenv SAL_XKEYBOARDGROUP 2     sets the keyboard group index to 2
    // keyboard group index must be in [1,4], may be specified in hex or decimal
    static char *pUseKeyboardExtension = getenv( "SAL_XKEYBOARDGROUP" );
    if ( pUseKeyboardExtension != NULL )
    {
        mbUseExtension = pUseKeyboardExtension[0] != '\0' ;
        if ( mbUseExtension )
            mnDefaultGroup = strtol( pUseKeyboardExtension, NULL, 0 );
        if ( mnDefaultGroup > XkbMaxKbdGroup )
            mnDefaultGroup = 0;
    }

    // query XServer support for XKB Extension,
    // do not call XQueryExtension() / XInitExtension() due to possible version
    // clashes !
    if ( mbUseExtension )
    {
        int nMajorExtOpcode;
        int nExtMajorVersion = XkbMajorVersion;
        int nExtMinorVersion = XkbMinorVersion;

        mbUseExtension = (sal_Bool)XkbQueryExtension( mpDisplay,
            &nMajorExtOpcode, (int*)&mnEventBase, (int*)&mnErrorBase,
            &nExtMajorVersion, &nExtMinorVersion );
    }

    // query notification for changes of the keyboard group
    if ( mbUseExtension )
    {
        #define XkbGroupMask (  XkbGroupStateMask | XkbGroupBaseMask \
                                | XkbGroupLatchMask | XkbGroupLockMask )

        mbUseExtension = XkbSelectEventDetails( mpDisplay,
            XkbUseCoreKbd, XkbStateNotify, XkbGroupMask, XkbGroupMask );
    }

    // query initial keyboard group
    if ( mbUseExtension )
    {
        XkbStateRec aStateRecord;
        XkbGetState( mpDisplay, XkbUseCoreKbd, &aStateRecord );
        mnGroup = aStateRecord.group;
    }

    #endif // __XKeyboardExtension__
}

void
SalI18N_KeyboardExtension::Dispatch( XEvent*
#if __XKeyboardExtension__
pEvent
#endif
)
{
    #if __XKeyboardExtension__

    // must the event be handled?
    if (   !mbUseExtension
        || (pEvent->type != mnEventBase) )
        return;

    // only handle state notify events for now, and only interested
    // in group details
    sal_uInt32 nXKBType = ((XkbAnyEvent*)pEvent)->xkb_type;
    switch ( nXKBType )
    {
        case XkbStateNotify:

            mnGroup = ((XkbStateNotifyEvent*)pEvent)->group;
            break;

        default:

            #if OSL_DEBUG_LEVEL > 1
            fprintf(stderr, "Got unrequested XkbAnyEvent %#x/%i\n",
                    static_cast<unsigned int>(nXKBType), static_cast<int>(nXKBType) );
            #endif
            break;
    }
    #endif // __XKeyboardExtension__
}

#if __XKeyboardExtension__
sal_uInt32
SalI18N_KeyboardExtension::LookupKeysymInGroup( sal_uInt32 nKeyCode,
                                                 sal_uInt32 nShiftState,
                                                   sal_uInt32 nGroup ) const
#else
sal_uInt32
SalI18N_KeyboardExtension::LookupKeysymInGroup( sal_uInt32,sal_uInt32,sal_uInt32 ) const
#endif
{
    #if __XKeyboardExtension__

    if ( !mbUseExtension )
        return NoSymbol;

    nShiftState &= ShiftMask;

    KeySym      nKeySymbol;
    nKeySymbol = XkbKeycodeToKeysym( mpDisplay, nKeyCode, nGroup, nShiftState );
    return nKeySymbol;

    #else

    return NoSymbol;

    #endif // __XKeyboardExtension__
}

<commit_msg>INTEGRATION: CWS changefileheader (1.9.246); FILE MERGED 2008/04/01 13:01:58 thb 1.9.246.2: #i85898# Stripping all external header guards 2008/03/28 15:45:24 rt 1.9.246.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: i18n_xkb.cxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

#include <stdio.h>

#include "saldisp.hxx"
#include "saldata.hxx"
#include "i18n_xkb.hxx"

SalI18N_KeyboardExtension::SalI18N_KeyboardExtension( Display*
#if __XKeyboardExtension__
pDisplay
#endif
)
    : mbUseExtension( (sal_Bool)__XKeyboardExtension__ ),
      mnDefaultGroup( 0 )
{
    #if __XKeyboardExtension__

    mpDisplay = pDisplay;

    // allow user to set the default keyboard group idx or to disable the usage
    // of x keyboard extension at all:
    //      setenv SAL_XKEYBOARDGROUP       disables keyboard extension
    //      setenv SAL_XKEYBOARDGROUP 2     sets the keyboard group index to 2
    // keyboard group index must be in [1,4], may be specified in hex or decimal
    static char *pUseKeyboardExtension = getenv( "SAL_XKEYBOARDGROUP" );
    if ( pUseKeyboardExtension != NULL )
    {
        mbUseExtension = pUseKeyboardExtension[0] != '\0' ;
        if ( mbUseExtension )
            mnDefaultGroup = strtol( pUseKeyboardExtension, NULL, 0 );
        if ( mnDefaultGroup > XkbMaxKbdGroup )
            mnDefaultGroup = 0;
    }

    // query XServer support for XKB Extension,
    // do not call XQueryExtension() / XInitExtension() due to possible version
    // clashes !
    if ( mbUseExtension )
    {
        int nMajorExtOpcode;
        int nExtMajorVersion = XkbMajorVersion;
        int nExtMinorVersion = XkbMinorVersion;

        mbUseExtension = (sal_Bool)XkbQueryExtension( mpDisplay,
            &nMajorExtOpcode, (int*)&mnEventBase, (int*)&mnErrorBase,
            &nExtMajorVersion, &nExtMinorVersion );
    }

    // query notification for changes of the keyboard group
    if ( mbUseExtension )
    {
        #define XkbGroupMask (  XkbGroupStateMask | XkbGroupBaseMask \
                                | XkbGroupLatchMask | XkbGroupLockMask )

        mbUseExtension = XkbSelectEventDetails( mpDisplay,
            XkbUseCoreKbd, XkbStateNotify, XkbGroupMask, XkbGroupMask );
    }

    // query initial keyboard group
    if ( mbUseExtension )
    {
        XkbStateRec aStateRecord;
        XkbGetState( mpDisplay, XkbUseCoreKbd, &aStateRecord );
        mnGroup = aStateRecord.group;
    }

    #endif // __XKeyboardExtension__
}

void
SalI18N_KeyboardExtension::Dispatch( XEvent*
#if __XKeyboardExtension__
pEvent
#endif
)
{
    #if __XKeyboardExtension__

    // must the event be handled?
    if (   !mbUseExtension
        || (pEvent->type != mnEventBase) )
        return;

    // only handle state notify events for now, and only interested
    // in group details
    sal_uInt32 nXKBType = ((XkbAnyEvent*)pEvent)->xkb_type;
    switch ( nXKBType )
    {
        case XkbStateNotify:

            mnGroup = ((XkbStateNotifyEvent*)pEvent)->group;
            break;

        default:

            #if OSL_DEBUG_LEVEL > 1
            fprintf(stderr, "Got unrequested XkbAnyEvent %#x/%i\n",
                    static_cast<unsigned int>(nXKBType), static_cast<int>(nXKBType) );
            #endif
            break;
    }
    #endif // __XKeyboardExtension__
}

#if __XKeyboardExtension__
sal_uInt32
SalI18N_KeyboardExtension::LookupKeysymInGroup( sal_uInt32 nKeyCode,
                                                 sal_uInt32 nShiftState,
                                                   sal_uInt32 nGroup ) const
#else
sal_uInt32
SalI18N_KeyboardExtension::LookupKeysymInGroup( sal_uInt32,sal_uInt32,sal_uInt32 ) const
#endif
{
    #if __XKeyboardExtension__

    if ( !mbUseExtension )
        return NoSymbol;

    nShiftState &= ShiftMask;

    KeySym      nKeySymbol;
    nKeySymbol = XkbKeycodeToKeysym( mpDisplay, nKeyCode, nGroup, nShiftState );
    return nKeySymbol;

    #else

    return NoSymbol;

    #endif // __XKeyboardExtension__
}

<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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.
//
// This code glues the RLZ library DLL with Chrome. It allows Chrome to work
// with or without the DLL being present. If the DLL is not present the
// functions do nothing and just return false.

#include "chrome/browser/rlz/rlz.h"

#include <windows.h>
#include <process.h>

#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/task.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/template_url_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/env_vars.h"
#include "chrome/installer/util/google_update_settings.h"
//#include "chrome/common/pref_names.h"
//#include "chrome/common/pref_service.h"

namespace {

// The maximum length of an access points RLZ in wide chars.
const DWORD kMaxRlzLength = 64;

// The RLZ is a DLL that might not be present in the system. We load it
// as needed but never unload it.
volatile HMODULE rlz_dll = NULL;

enum {
  ACCESS_VALUES_STALE,      // Possibly new values available.
  ACCESS_VALUES_FRESH       // The cached values are current.
};

// Tracks if we have tried and succeeded sending the ping. This helps us
// decide if we need to refresh the some cached strings.
volatile int access_values_state = ACCESS_VALUES_STALE;

extern "C" {
typedef bool (*RecordProductEventFn)(RLZTracker::Product product,
                                     RLZTracker::AccessPoint point,
                                     RLZTracker::Event event_id,
                                     void* reserved);

typedef bool (*GetAccessPointRlzFn)(RLZTracker::AccessPoint point,
                                    wchar_t* rlz,
                                    DWORD rlz_size,
                                    void* reserved);

typedef bool (*ClearAllProductEventsFn)(RLZTracker::Product product,
                                        void* reserved);

typedef bool (*SendFinancialPingFn)(RLZTracker::Product product,
                                    RLZTracker::AccessPoint* access_points,
                                    const WCHAR* product_signature,
                                    const WCHAR* product_brand,
                                    const WCHAR* product_id,
                                    const WCHAR* product_lang,
                                    void* reserved);
}  // extern "C"

RecordProductEventFn record_event = NULL;
GetAccessPointRlzFn get_access_point = NULL;
ClearAllProductEventsFn clear_all_events = NULL;
SendFinancialPingFn send_ping = NULL;

template <typename FuncT>
FuncT WireExport(HMODULE module, const char* export_name) {
  void* entry_point = ::GetProcAddress(module, export_name);
  return (module)? reinterpret_cast<FuncT>(entry_point) : NULL;
}

HMODULE LoadRLZLibraryInternal(int directory_key) {
  std::wstring rlz_path;
  if (!PathService::Get(directory_key, &rlz_path))
    return NULL;
  file_util::AppendToPath(&rlz_path, L"rlz.dll");
  return ::LoadLibraryW(rlz_path.c_str());
}

bool LoadRLZLibrary(int directory_key) {
  rlz_dll = LoadRLZLibraryInternal(directory_key);
  if (!rlz_dll) {
    // As a last resort we can try the EXE directory.
    if (directory_key != base::DIR_EXE)
      rlz_dll = LoadRLZLibraryInternal(base::DIR_EXE);
  }
  if (rlz_dll) {
    record_event =
        WireExport<RecordProductEventFn>(rlz_dll, "RecordProductEvent");
    get_access_point =
        WireExport<GetAccessPointRlzFn>(rlz_dll, "GetAccessPointRlz");
    clear_all_events =
        WireExport<ClearAllProductEventsFn>(rlz_dll, "ClearAllProductEvents");
    send_ping =
        WireExport<SendFinancialPingFn>(rlz_dll, "SendFinancialPing");
    return true;
  }
  return false;
}

class DailyPingTask : public Task {
 public:
  virtual ~DailyPingTask() {
  }
  virtual void Run() {
    // We use a transient thread because we have no guarantees about
    // how long the RLZ lib can block us.
    _beginthread(PingNow, 0, NULL);
  }

 private:
  // Causes a ping to the server using WinInet. There is logic inside RLZ dll
  // that throttles it to a maximum of one ping per day.
  static void _cdecl PingNow(void*) {
    std::wstring lang;
    GoogleUpdateSettings::GetLanguage(&lang);
    if (lang.empty())
      lang = L"en";
    std::wstring brand;
    GoogleUpdateSettings::GetBrand(&brand);
    if (brand.empty())
      brand = L"GGLD";
    if (RLZTracker::SendFinancialPing(RLZTracker::CHROME, L"chrome",
                                      brand.c_str(), NULL, lang.c_str())) {
      access_values_state = ACCESS_VALUES_STALE;
    }
  }
};

// Performs late RLZ initialization and RLZ event recording for chrome.
// This task needs to run on the UI thread.
class DelayedInitTask : public Task {
 public:
  explicit DelayedInitTask(int directory_key, bool first_run)
      : directory_key_(directory_key), first_run_(first_run) {
  }
  virtual ~DelayedInitTask() {
  }
  virtual void Run() {
    if (!LoadRLZLibrary(directory_key_))
      return;
    // For non-interactive tests we don't do the rest of the initialization.
    if (::GetEnvironmentVariableW(env_vars::kHeadless, NULL, 0))
      return;
    if (first_run_) {
      // Record the installation of chrome.
      RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                     RLZTracker::CHROME_OMNIBOX,
                                     RLZTracker::INSTALL);
      RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                     RLZTracker::CHROME_HOME_PAGE,
                                     RLZTracker::INSTALL);
      // Record if google is the initial search provider.
      if (IsGoogleDefaultSearch()) {
        RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                       RLZTracker::CHROME_OMNIBOX,
                                       RLZTracker::SET_TO_GOOGLE);
      }
    }
    // Schedule the daily RLZ ping.
    base::Thread* thread = g_browser_process->file_thread();
    if (thread)
      thread->message_loop()->PostTask(FROM_HERE, new DailyPingTask());
  }

 private:
  bool IsGoogleDefaultSearch() {
    if (!g_browser_process)
      return false;
    std::wstring user_data_dir;
    if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
      return false;
    ProfileManager* profile_manager = g_browser_process->profile_manager();
    Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
    if (!profile)
      return false;
    const TemplateURL* url_template =
        profile->GetTemplateURLModel()->GetDefaultSearchProvider();
    if (!url_template)
      return false;
    return url_template->url()->HasGoogleBaseURLs();
  }

  int directory_key_;
  bool first_run_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(DelayedInitTask);
};

}  // namespace

bool RLZTracker::InitRlz(int directory_key) {
  return LoadRLZLibrary(directory_key);
}

bool RLZTracker::InitRlzDelayed(int directory_key, bool first_run) {
  // Schedule the delayed init items.
  const int kOneHundredSeconds = 100000;
  MessageLoop::current()->PostDelayedTask(FROM_HERE,
      new DelayedInitTask(directory_key, first_run), kOneHundredSeconds);
  return true;
}

bool RLZTracker::RecordProductEvent(Product product, AccessPoint point,
                                    Event event) {
  return (record_event) ? record_event(product, point, event, NULL) : false;
}

bool RLZTracker::ClearAllProductEvents(Product product) {
  return (clear_all_events) ? clear_all_events(product, NULL) : false;
}

// We implement caching of the answer of get_access_point() if the request
// is for CHROME_OMNIBOX. If we had a successful ping, then we update the
// cached value.

bool RLZTracker::GetAccessPointRlz(AccessPoint point, std::wstring* rlz) {
  static std::wstring cached_ommibox_rlz;
  if (!get_access_point)
    return false;
  if ((CHROME_OMNIBOX == point) &&
      (access_values_state == ACCESS_VALUES_FRESH)) {
    *rlz = cached_ommibox_rlz;
    return true;
  }
  wchar_t str_rlz[kMaxRlzLength];
  if (!get_access_point(point, str_rlz, kMaxRlzLength, NULL))
    return false;
  if (CHROME_OMNIBOX == point) {
    access_values_state = ACCESS_VALUES_FRESH;
    cached_ommibox_rlz.assign(str_rlz);
  }
  *rlz = str_rlz;
  return true;
}

bool RLZTracker::SendFinancialPing(Product product,
                                   const wchar_t* product_signature,
                                   const wchar_t* product_brand,
                                   const wchar_t* product_id,
                                   const wchar_t* product_lang) {
  AccessPoint points[] = {CHROME_OMNIBOX, CHROME_HOME_PAGE, NO_ACCESS_POINT};
  return (send_ping) ? send_ping(product, points, product_signature,
      product_brand, product_id, product_lang, NULL) : false;
}

<commit_msg>Try to re-land issue 3200 - it was causing trouble in the distributed tests - now does not try to load the dll in headless configs<commit_after>// Copyright (c) 2006-2008 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.
//
// This code glues the RLZ library DLL with Chrome. It allows Chrome to work
// with or without the DLL being present. If the DLL is not present the
// functions do nothing and just return false.

#include "chrome/browser/rlz/rlz.h"

#include <windows.h>
#include <process.h>

#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/task.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/template_url_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/env_vars.h"
#include "chrome/installer/util/google_update_settings.h"
//#include "chrome/common/pref_names.h"
//#include "chrome/common/pref_service.h"

namespace {

// The maximum length of an access points RLZ in wide chars.
const DWORD kMaxRlzLength = 64;

// The RLZ is a DLL that might not be present in the system. We load it
// as needed but never unload it.
volatile HMODULE rlz_dll = NULL;

enum {
  ACCESS_VALUES_STALE,      // Possibly new values available.
  ACCESS_VALUES_FRESH       // The cached values are current.
};

// Tracks if we have tried and succeeded sending the ping. This helps us
// decide if we need to refresh the some cached strings.
volatile int access_values_state = ACCESS_VALUES_STALE;

extern "C" {
typedef bool (*RecordProductEventFn)(RLZTracker::Product product,
                                     RLZTracker::AccessPoint point,
                                     RLZTracker::Event event_id,
                                     void* reserved);

typedef bool (*GetAccessPointRlzFn)(RLZTracker::AccessPoint point,
                                    wchar_t* rlz,
                                    DWORD rlz_size,
                                    void* reserved);

typedef bool (*ClearAllProductEventsFn)(RLZTracker::Product product,
                                        void* reserved);

typedef bool (*SendFinancialPingFn)(RLZTracker::Product product,
                                    RLZTracker::AccessPoint* access_points,
                                    const WCHAR* product_signature,
                                    const WCHAR* product_brand,
                                    const WCHAR* product_id,
                                    const WCHAR* product_lang,
                                    void* reserved);
}  // extern "C"

RecordProductEventFn record_event = NULL;
GetAccessPointRlzFn get_access_point = NULL;
ClearAllProductEventsFn clear_all_events = NULL;
SendFinancialPingFn send_ping = NULL;

template <typename FuncT>
FuncT WireExport(HMODULE module, const char* export_name) {
  void* entry_point = ::GetProcAddress(module, export_name);
  return (module)? reinterpret_cast<FuncT>(entry_point) : NULL;
}

HMODULE LoadRLZLibraryInternal(int directory_key) {
  std::wstring rlz_path;
  if (!PathService::Get(directory_key, &rlz_path))
    return NULL;
  file_util::AppendToPath(&rlz_path, L"rlz.dll");
  return ::LoadLibraryW(rlz_path.c_str());
}

bool LoadRLZLibrary(int directory_key) {
  rlz_dll = LoadRLZLibraryInternal(directory_key);
  if (!rlz_dll) {
    // As a last resort we can try the EXE directory.
    if (directory_key != base::DIR_EXE)
      rlz_dll = LoadRLZLibraryInternal(base::DIR_EXE);
  }
  if (rlz_dll) {
    record_event =
        WireExport<RecordProductEventFn>(rlz_dll, "RecordProductEvent");
    get_access_point =
        WireExport<GetAccessPointRlzFn>(rlz_dll, "GetAccessPointRlz");
    clear_all_events =
        WireExport<ClearAllProductEventsFn>(rlz_dll, "ClearAllProductEvents");
    send_ping =
        WireExport<SendFinancialPingFn>(rlz_dll, "SendFinancialPing");
    return (record_event && get_access_point && clear_all_events && send_ping);
  }
  return false;
}

class DailyPingTask : public Task {
 public:
  virtual ~DailyPingTask() {
  }
  virtual void Run() {
    // We use a transient thread because we have no guarantees about
    // how long the RLZ lib can block us.
    _beginthread(PingNow, 0, NULL);
  }

 private:
  // Causes a ping to the server using WinInet. There is logic inside RLZ dll
  // that throttles it to a maximum of one ping per day.
  static void _cdecl PingNow(void*) {
    std::wstring lang;
    GoogleUpdateSettings::GetLanguage(&lang);
    if (lang.empty())
      lang = L"en";
    std::wstring brand;
    GoogleUpdateSettings::GetBrand(&brand);
    if (brand.empty())
      brand = L"GGLD";
    if (RLZTracker::SendFinancialPing(RLZTracker::CHROME, L"chrome",
                                      brand.c_str(), NULL, lang.c_str())) {
      access_values_state = ACCESS_VALUES_STALE;
    }
  }
};

// Performs late RLZ initialization and RLZ event recording for chrome.
// This task needs to run on the UI thread.
class DelayedInitTask : public Task {
 public:
  explicit DelayedInitTask(int directory_key, bool first_run)
      : directory_key_(directory_key), first_run_(first_run) {
  }
  virtual ~DelayedInitTask() {
  }
  virtual void Run() {
    // For non-interactive tests we don't do the rest of the initialization
    // because sometimes the very act of loading the dll causes QEMU to crash.
    if (::GetEnvironmentVariableW(env_vars::kHeadless, NULL, 0))
      return;
    if (!LoadRLZLibrary(directory_key_))
      return;
    // Do the initial event recording if is the first run or if we have an
    // empty rlz which means we haven't got a chance to do it.
    std::wstring omnibox_rlz;
    RLZTracker::GetAccessPointRlz(RLZTracker::CHROME_OMNIBOX, &omnibox_rlz);

    if (first_run_ || omnibox_rlz.empty()) {
      // Record the installation of chrome.
      RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                     RLZTracker::CHROME_OMNIBOX,
                                     RLZTracker::INSTALL);
      RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                     RLZTracker::CHROME_HOME_PAGE,
                                     RLZTracker::INSTALL);
      // Record if google is the initial search provider.
      if (IsGoogleDefaultSearch()) {
        RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                       RLZTracker::CHROME_OMNIBOX,
                                       RLZTracker::SET_TO_GOOGLE);
      }
    }
    // Schedule the daily RLZ ping.
    base::Thread* thread = g_browser_process->file_thread();
    if (thread)
      thread->message_loop()->PostTask(FROM_HERE, new DailyPingTask());
  }

 private:
  bool IsGoogleDefaultSearch() {
    if (!g_browser_process)
      return false;
    std::wstring user_data_dir;
    if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
      return false;
    ProfileManager* profile_manager = g_browser_process->profile_manager();
    Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
    if (!profile)
      return false;
    const TemplateURL* url_template =
        profile->GetTemplateURLModel()->GetDefaultSearchProvider();
    if (!url_template)
      return false;
    return url_template->url()->HasGoogleBaseURLs();
  }

  int directory_key_;
  bool first_run_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(DelayedInitTask);
};

}  // namespace

bool RLZTracker::InitRlz(int directory_key) {
  return LoadRLZLibrary(directory_key);
}

bool RLZTracker::InitRlzDelayed(int directory_key, bool first_run) {
  // Schedule the delayed init items.
  const int kTwentySeconds = 20 * 1000;
  MessageLoop::current()->PostDelayedTask(FROM_HERE,
      new DelayedInitTask(directory_key, first_run), kTwentySeconds);
  return true;
}

bool RLZTracker::RecordProductEvent(Product product, AccessPoint point,
                                    Event event) {
  return (record_event) ? record_event(product, point, event, NULL) : false;
}

bool RLZTracker::ClearAllProductEvents(Product product) {
  return (clear_all_events) ? clear_all_events(product, NULL) : false;
}

// We implement caching of the answer of get_access_point() if the request
// is for CHROME_OMNIBOX. If we had a successful ping, then we update the
// cached value.

bool RLZTracker::GetAccessPointRlz(AccessPoint point, std::wstring* rlz) {
  static std::wstring cached_ommibox_rlz;
  if (!get_access_point)
    return false;
  if ((CHROME_OMNIBOX == point) &&
      (access_values_state == ACCESS_VALUES_FRESH)) {
    *rlz = cached_ommibox_rlz;
    return true;
  }
  wchar_t str_rlz[kMaxRlzLength];
  if (!get_access_point(point, str_rlz, kMaxRlzLength, NULL))
    return false;
  if (CHROME_OMNIBOX == point) {
    access_values_state = ACCESS_VALUES_FRESH;
    cached_ommibox_rlz.assign(str_rlz);
  }
  *rlz = str_rlz;
  return true;
}

bool RLZTracker::SendFinancialPing(Product product,
                                   const wchar_t* product_signature,
                                   const wchar_t* product_brand,
                                   const wchar_t* product_id,
                                   const wchar_t* product_lang) {
  AccessPoint points[] = {CHROME_OMNIBOX, CHROME_HOME_PAGE, NO_ACCESS_POINT};
  return (send_ping) ? send_ping(product, points, product_signature,
      product_brand, product_id, product_lang, NULL) : false;
}

<|endoftext|>