<commit_before>#include "Physics.hpp"

#include "../Physics/RigidBody.hpp"
#include "../Physics/Shape.hpp"
#include "../Util/Json.hpp"

namespace Component {

    Json::Value Physics::Save() const {
        Json::Value component;
        component["velocity"] = Json::SaveVec3(velocity);
        component["maxVelocity"] = maxVelocity;
        component["angularVelocity"] = Json::SaveVec3(angularVelocity);
        component["maxAngularVelocity"] = maxAngularVelocity;
        component["acceleration"] = Json::SaveVec3(acceleration);
        component["angularAcceleration"] = Json::SaveVec3(angularAcceleration);
        component["velocityDragFactor"] = velocityDragFactor;
        component["angularDragFactor"] = angularDragFactor;
        component["gravityFactor"] = gravityFactor;
        component["momentOfInertia"] = Json::SaveVec3(momentOfInertia);

        Json::Value componentShape;
        Json::Value concreteShape;
        ::Physics::Shape& shape = rigidBody->GetShape();
        switch (shape.GetKind()) {
            case ::Physics::Shape::Kind::Sphere: {
                componentShape["sphere"] = concreteShape;
                break;
            }
            case ::Physics::Shape::Kind::Plane: {
                auto planeData = shape.GetPlaneData();
                concreteShape["normal"] = Json::SaveVec3(planeData->normal);
                concreteShape["planeCoeff"] = planeData->planeCoeff;
                componentShape["plane"] = concreteShape;
                break;
            }
        }
        component["shape"] = componentShape;
        return component;
    }

    void Physics::Load(const Json::Value& node) {
        delete rigidBody;
        rigidBody = nullptr;

        velocity = Json::LoadVec3(node["velocity"]);
        maxVelocity = node.get("maxVelocity", 20.f).asFloat();
        angularVelocity = Json::LoadVec3(node["angularVelocity"]);
        maxAngularVelocity = node.get("maxAngularVelocity", 2.f).asFloat();
        acceleration = Json::LoadVec3(node["acceleration"]);
        angularAcceleration = Json::LoadVec3(node["angularAcceleration"]);
        velocityDragFactor = node.get("velocityDragFactor", 1.f).asFloat();
        angularDragFactor = node.get("angularDragFactor", 1.f).asFloat();
        gravityFactor = node.get("gravityFactor", 0.f).asFloat();
        momentOfInertia = Json::LoadVec3(node["momentOfInertia"]);

        auto shape = node.get("shape", {});
        if (shape.isMember("sphere")) {
            auto sphere = shape.get("sphere", {});
            auto radius = sphere.get("radius", 1.0f).asFloat();
            auto shape = new ::Physics::Shape(::Physics::Shape::Sphere(radius));
            rigidBody = new ::Physics::RigidBody(shape, 1.0f);
        }
        else if (shape.isMember("plane")) {
            auto plane = shape.get("plane", {});
            auto normal = Json::LoadVec3(plane.get("normal", {}));
            auto planeCoeff = plane.get("planeCoeff", 0.0f).asFloat();
            auto shape = new ::Physics::Shape(::Physics::Shape::Plane(normal, planeCoeff));
            rigidBody = new ::Physics::RigidBody(shape, 1.0f);
        }

        assert(rigidBody);
    }

    ::Physics::Shape& Physics::GetShape() {
        return rigidBody->GetShape();
    }

    void Physics::SetShape(::Physics::Shape* shape) {
        rigidBody->SetShape(shape);
    }

    ::Physics::RigidBody& Physics::GetRigidBody() {
        return *rigidBody;
    }

    Physics::Physics(Entity* entity) : SuperComponent(entity) {
        // Temporary until creation via managers works properly (this is just
        // to have some default resources).
        auto shape = new ::Physics::Shape(::Physics::Shape::Sphere(2.0f));
        rigidBody = new ::Physics::RigidBody(shape, 1.0f);
    }

}
<commit_msg>Save sphere data if that's the shape.<commit_after>#include "Physics.hpp"

#include "../Physics/RigidBody.hpp"
#include "../Physics/Shape.hpp"
#include "../Util/Json.hpp"

namespace Component {

    Json::Value Physics::Save() const {
        Json::Value component;
        component["velocity"] = Json::SaveVec3(velocity);
        component["maxVelocity"] = maxVelocity;
        component["angularVelocity"] = Json::SaveVec3(angularVelocity);
        component["maxAngularVelocity"] = maxAngularVelocity;
        component["acceleration"] = Json::SaveVec3(acceleration);
        component["angularAcceleration"] = Json::SaveVec3(angularAcceleration);
        component["velocityDragFactor"] = velocityDragFactor;
        component["angularDragFactor"] = angularDragFactor;
        component["gravityFactor"] = gravityFactor;
        component["momentOfInertia"] = Json::SaveVec3(momentOfInertia);

        Json::Value componentShape;
        Json::Value concreteShape;
        ::Physics::Shape& shape = rigidBody->GetShape();
        switch (shape.GetKind()) {
            case ::Physics::Shape::Kind::Sphere: {
                auto sphereData = shape.GetSphereData();
                concreteShape["radius"] = sphereData->radius;
                componentShape["sphere"] = concreteShape;
                break;
            }
            case ::Physics::Shape::Kind::Plane: {
                auto planeData = shape.GetPlaneData();
                concreteShape["normal"] = Json::SaveVec3(planeData->normal);
                concreteShape["planeCoeff"] = planeData->planeCoeff;
                componentShape["plane"] = concreteShape;
                break;
            }
        }
        component["shape"] = componentShape;
        return component;
    }

    void Physics::Load(const Json::Value& node) {
        delete rigidBody;
        rigidBody = nullptr;

        velocity = Json::LoadVec3(node["velocity"]);
        maxVelocity = node.get("maxVelocity", 20.f).asFloat();
        angularVelocity = Json::LoadVec3(node["angularVelocity"]);
        maxAngularVelocity = node.get("maxAngularVelocity", 2.f).asFloat();
        acceleration = Json::LoadVec3(node["acceleration"]);
        angularAcceleration = Json::LoadVec3(node["angularAcceleration"]);
        velocityDragFactor = node.get("velocityDragFactor", 1.f).asFloat();
        angularDragFactor = node.get("angularDragFactor", 1.f).asFloat();
        gravityFactor = node.get("gravityFactor", 0.f).asFloat();
        momentOfInertia = Json::LoadVec3(node["momentOfInertia"]);

        auto shape = node.get("shape", {});
        if (shape.isMember("sphere")) {
            auto sphere = shape.get("sphere", {});
            auto radius = sphere.get("radius", 1.0f).asFloat();
            auto shape = new ::Physics::Shape(::Physics::Shape::Sphere(radius));
            rigidBody = new ::Physics::RigidBody(shape, 1.0f);
        }
        else if (shape.isMember("plane")) {
            auto plane = shape.get("plane", {});
            auto normal = Json::LoadVec3(plane.get("normal", {}));
            auto planeCoeff = plane.get("planeCoeff", 0.0f).asFloat();
            auto shape = new ::Physics::Shape(::Physics::Shape::Plane(normal, planeCoeff));
            rigidBody = new ::Physics::RigidBody(shape, 1.0f);
        }

        assert(rigidBody);
    }

    ::Physics::Shape& Physics::GetShape() {
        return rigidBody->GetShape();
    }

    void Physics::SetShape(::Physics::Shape* shape) {
        rigidBody->SetShape(shape);
    }

    ::Physics::RigidBody& Physics::GetRigidBody() {
        return *rigidBody;
    }

    Physics::Physics(Entity* entity) : SuperComponent(entity) {
        // Temporary until creation via managers works properly (this is just
        // to have some default resources).
        auto shape = new ::Physics::Shape(::Physics::Shape::Sphere(2.0f));
        rigidBody = new ::Physics::RigidBody(shape, 1.0f);
    }

}
<|endoftext|>


<commit_before>#pragma once

#include <glm/glm.hpp>
#include <openvr.h>
#include <openvr_capi.h>

/// Handles communication with VR devices using OpenVR.
class VRManager {
    friend class Hub;

    public:
        /// Check if the VRManger is active.
        /**
         * @return Whether hmd is present or not.
         */
        bool Active() const;

        /// Sync VR device pose(s).
        void Sync();

        /// Recommended render target size to minimize pixel stretching.
        /**
         * @return Recommended size (in pixels).
         */
        glm::vec2 GetRecommendedRenderTargetSize() const;

        /// Returns the transform for the HMD.
        /**
         * @return The HMD translation matrix.
         */
        glm::mat4 GetHMDPoseMatrix() const;

        /// Returns the transform for the controllers
        /**
         * @param controlID Which controller to get the matrix for (1 = left, 2 = right).
         * @return The Controllers translation matrix.
         */
        glm::mat4 GetControllerPoseMatrix(int controlID) const;

        /// Returns the transform between the view space and eye space.
        /**
         * @param eye Which eye the function should return the eye matrix for.
         * @return The eye matrix.
         */
        glm::mat4 GetHMDEyeToHeadMatrix(vr::Hmd_Eye eye) const;

        /// Returns the projection matrix to use for the specified eye.
        /**
         * @param eye Which eye the function should return the eye matrix for.
         * @param zNear Distance to the near clip plane in meters.
         * @param zFar Distance to the far clip plane in meters.
         * @return The projection matrix.
         */
        glm::mat4 GetHMDProjectionMatrix(vr::Hmd_Eye eye, float zNear, float zFar) const;

        /// Submit a texture to an eye.
        /**
         * @param eye Which eye to submit texture.
         * @param texture Texture to submit.
         */
        void Submit(vr::Hmd_Eye eye, vr::Texture_t* texture) const;

        /// Get scale of player.
        /**
         * @return Scale to get.
         */
        float GetScale() const;

        /// Set scale of player.
        /**
         * @param scale Scale to set.
         */
        void SetScale(float scale);

        /// Gets if certain button is pressed (Only trigger for now)
        /**
         * @param buttonID the button we want to check is pressed.
         * @return whether certain button is pressed or not.
         */
        bool GetInput(vr::EVRButtonId buttonID);

    private:
        VRManager();
        ~VRManager();
        VRManager(VRManager const&) = delete;
        void operator=(VRManager const&) = delete;

        static glm::mat4 ConvertMatrix(const vr::HmdMatrix34_t& mat);
        static glm::mat4 ConvertMatrix(const vr::HmdMatrix44_t& mat);

        float scale;
        vr::IVRSystem* vrSystem;
        vr::TrackedDevicePose_t tracedDevicePoseArray[vr::k_unMaxTrackedDeviceCount];
        glm::mat4 deviceTransforms[vr::k_unMaxTrackedDeviceCount];

        bool pressedTrackedDevice[vr::k_unMaxTrackedDeviceCount];
};
<commit_msg>Fix compilation with MinGW<commit_after>#pragma once

#include <glm/glm.hpp>
#include <openvr.h>

/// Handles communication with VR devices using OpenVR.
class VRManager {
    friend class Hub;

    public:
        /// Check if the VRManger is active.
        /**
         * @return Whether hmd is present or not.
         */
        bool Active() const;

        /// Sync VR device pose(s).
        void Sync();

        /// Recommended render target size to minimize pixel stretching.
        /**
         * @return Recommended size (in pixels).
         */
        glm::vec2 GetRecommendedRenderTargetSize() const;

        /// Returns the transform for the HMD.
        /**
         * @return The HMD translation matrix.
         */
        glm::mat4 GetHMDPoseMatrix() const;

        /// Returns the transform for the controllers
        /**
         * @param controlID Which controller to get the matrix for (1 = left, 2 = right).
         * @return The Controllers translation matrix.
         */
        glm::mat4 GetControllerPoseMatrix(int controlID) const;

        /// Returns the transform between the view space and eye space.
        /**
         * @param eye Which eye the function should return the eye matrix for.
         * @return The eye matrix.
         */
        glm::mat4 GetHMDEyeToHeadMatrix(vr::Hmd_Eye eye) const;

        /// Returns the projection matrix to use for the specified eye.
        /**
         * @param eye Which eye the function should return the eye matrix for.
         * @param zNear Distance to the near clip plane in meters.
         * @param zFar Distance to the far clip plane in meters.
         * @return The projection matrix.
         */
        glm::mat4 GetHMDProjectionMatrix(vr::Hmd_Eye eye, float zNear, float zFar) const;

        /// Submit a texture to an eye.
        /**
         * @param eye Which eye to submit texture.
         * @param texture Texture to submit.
         */
        void Submit(vr::Hmd_Eye eye, vr::Texture_t* texture) const;

        /// Get scale of player.
        /**
         * @return Scale to get.
         */
        float GetScale() const;

        /// Set scale of player.
        /**
         * @param scale Scale to set.
         */
        void SetScale(float scale);

        /// Gets if certain button is pressed (Only trigger for now)
        /**
         * @param buttonID the button we want to check is pressed.
         * @return whether certain button is pressed or not.
         */
        bool GetInput(vr::EVRButtonId buttonID);

    private:
        VRManager();
        ~VRManager();
        VRManager(VRManager const&) = delete;
        void operator=(VRManager const&) = delete;

        static glm::mat4 ConvertMatrix(const vr::HmdMatrix34_t& mat);
        static glm::mat4 ConvertMatrix(const vr::HmdMatrix44_t& mat);

        float scale;
        vr::IVRSystem* vrSystem;
        vr::TrackedDevicePose_t tracedDevicePoseArray[vr::k_unMaxTrackedDeviceCount];
        glm::mat4 deviceTransforms[vr::k_unMaxTrackedDeviceCount];

        bool pressedTrackedDevice[vr::k_unMaxTrackedDeviceCount];
};
<|endoftext|>


<commit_before>#include "process.h"
#include <iostream>

using namespace std;

int main() {
  cout << "Example 1 - simple echo process" << endl;
  Process process1("echo \"Hello World\"", "", [](const char *bytes, size_t n) {
    cout << "Output from stdout: " << std::string(bytes, n);
  });
  auto exit_code=process1.get_exit_code();
  cout << "Example 1 process returned: " << exit_code << endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));

  cout << endl << "Example 2 - cd into nonexistent directory" << endl;
  Process process2("cd nonexistent_directory", "", [](const char *bytes, size_t n) {
    cout << "Output from stdout: " << std::string(bytes, n);
  }, [](const char *bytes, size_t n) {
    cout << "Output from stderr: " << std::string(bytes, n);
  });
  exit_code=process2.get_exit_code();
  cout << "Example 2 process returned: " << exit_code << endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));

  cout << endl << "Example 3 - async sleep process" << endl;
  std::thread thread3([]() {
    Process process3("sleep 5");
    auto exit_code=process3.get_exit_code();
    cout << "Example 3 process returned (" << (exit_code==0?"success":"failure") << "): " << exit_code << endl;
  });
  thread3.detach();
  std::this_thread::sleep_for(std::chrono::seconds(10));

  cout << endl << "Example 4 - killing async sleep process after 5 seconds" << endl;
  auto process4=std::make_shared<Process>("sleep 10");
  std::thread thread4([process4]() {
    auto exit_code=process4->get_exit_code();
    cout << "Example 4 process returned (" << (exit_code==0?"success":"failure") << "): " << exit_code << endl;
  });
  thread4.detach();
  std::this_thread::sleep_for(std::chrono::seconds(5));
  Process::kill(process4->get_id());
  std::this_thread::sleep_for(std::chrono::seconds(5));

#if !defined(_WIN32) || defined(MSYS_PROCESS_USE_SH)
  //Example 5 only works when having access to the sh command (for multiple commands)
  //On Windows: install MSYS2 (https://msys2.github.io)
  cout << endl << "Example 5 - multiple commands, stdout and stderr" << endl;
  Process process5("echo Hello && ls an_incorrect_path", "", [](const char *bytes, size_t n) {
    cout << "Output from stdout: " << std::string(bytes, n);
  }, [](const char *bytes, size_t n) {
    cout << "Output from stderr: " << std::string(bytes, n);
  });
  exit_code=process5.get_exit_code();
  cout << "Example 5 process returned: " << exit_code << endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));

  //Example 6 only works when having access to the bash command
  //On Windows: install MSYS2 (https://msys2.github.io)
  cout << endl << "Example 6 - run bash with input from stdin" << endl;
  Process process6("bash", "", [](const char *bytes, size_t n) {
    cout << "Output from stdout: " << std::string(bytes, n);
  }, nullptr, true);
  process6.write("echo Hello from bash\n");
  process6.write("exit\n");
  exit_code=process6.get_exit_code();
  cout << "Example 6 process returned: " << exit_code << endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));

  //Example 7 only works when having access to the cat command
  //On Windows: install MSYS2 (https://msys2.github.io)
  cout << endl << "Example 7 - send data to cat through stdin" << endl;
  Process process7("cat", "", [](const char *bytes, size_t n) {
    cout << "Output from stdout: " << std::string(bytes, n);
  }, nullptr, true);
  process7.write("Hello cat\n");
  process7.close_stdin();
  exit_code=process7.get_exit_code();
  cout << "Example 7 process returned: " << exit_code << endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));
#endif
  return 0;
}
<commit_msg>Improved examples<commit_after>#include "process.h"
#include <iostream>

using namespace std;

int main() {
  cout << "Example 1 - the mandatory Hello World" << endl;
  Process process1("echo Hello World", "", [](const char *bytes, size_t n) {
    cout << "Output from stdout: " << std::string(bytes, n);
  });
  auto exit_code=process1.get_exit_code();
  cout << "Example 1 process returned: " << exit_code << " (" << (exit_code==0?"success":"failure") << ")" << endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));

  cout << endl << "Example 2 - cd into nonexistent directory" << endl;
  Process process2("cd nonexistent_directory", "", [](const char *bytes, size_t n) {
    cout << "Output from stdout: " << std::string(bytes, n);
  }, [](const char *bytes, size_t n) {
    cout << "Output from stderr: " << std::string(bytes, n);
  });
  exit_code=process2.get_exit_code();
  cout << "Example 2 process returned: " << exit_code << " (" << (exit_code==0?"success":"failure") << ")" << endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));

  cout << endl << "Example 3 - async sleep process" << endl;
  std::thread thread3([]() {
    Process process3("sleep 5");
    auto exit_code=process3.get_exit_code();
    cout << "Example 3 process returned: " << exit_code << " (" << (exit_code==0?"success":"failure") << ")" << endl;
  });
  thread3.detach();
  std::this_thread::sleep_for(std::chrono::seconds(10));

  cout << endl << "Example 4 - killing async sleep process after 5 seconds" << endl;
  auto process4=std::make_shared<Process>("sleep 10");
  std::thread thread4([process4]() {
    auto exit_code=process4->get_exit_code();
    cout << "Example 4 process returned: " << exit_code << " (" << (exit_code==0?"success":"failure") << ")" << endl;
  });
  thread4.detach();
  std::this_thread::sleep_for(std::chrono::seconds(5));
  Process::kill(process4->get_id());
  std::this_thread::sleep_for(std::chrono::seconds(5));

#if !defined(_WIN32) || defined(MSYS_PROCESS_USE_SH)
  //Example 5 only works when having access to the sh command (for multiple commands)
  //On Windows: install MSYS2 (https://msys2.github.io)
  cout << endl << "Example 5 - multiple commands, stdout and stderr" << endl;
  Process process5("echo Hello && ls an_incorrect_path", "", [](const char *bytes, size_t n) {
    cout << "Output from stdout: " << std::string(bytes, n);
  }, [](const char *bytes, size_t n) {
    cout << "Output from stderr: " << std::string(bytes, n);
  });
  exit_code=process5.get_exit_code();
  cout << "Example 5 process returned: " << exit_code << " (" << (exit_code==0?"success":"failure") << ")" << endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));

  //Example 6 only works when having access to the bash command
  //On Windows: install MSYS2 (https://msys2.github.io)
  cout << endl << "Example 6 - run bash with input from stdin" << endl;
  Process process6("bash", "", [](const char *bytes, size_t n) {
    cout << "Output from stdout: " << std::string(bytes, n);
  }, nullptr, true);
  process6.write("echo Hello from bash\n");
  process6.write("exit\n");
  exit_code=process6.get_exit_code();
  cout << "Example 6 process returned: " << exit_code << " (" << (exit_code==0?"success":"failure") << ")" << endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));

  //Example 7 only works when having access to the cat command
  //On Windows: install MSYS2 (https://msys2.github.io)
  cout << endl << "Example 7 - send data to cat through stdin" << endl;
  Process process7("cat", "", [](const char *bytes, size_t n) {
    cout << "Output from stdout: " << std::string(bytes, n);
  }, nullptr, true);
  process7.write("Hello cat\n");
  process7.close_stdin();
  exit_code=process7.get_exit_code();
  cout << "Example 7 process returned: " << exit_code << " (" << (exit_code==0?"success":"failure") << ")" << endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));
#endif
  return 0;
}
<|endoftext|>


<commit_before>//===-- ItaniumABILanguageRuntime.cpp --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "ItaniumABILanguageRuntime.h"

#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"

#include <vector>

using namespace lldb;
using namespace lldb_private;

static const char *pluginName = "ItaniumABILanguageRuntime";
static const char *pluginDesc = "Itanium ABI for the C++ language";
static const char *pluginShort = "language.itanium";
static const char *vtable_demangled_prefix = "vtable for ";

bool
ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
{
    return in_value.IsPossibleCPlusPlusDynamicType();
}

bool
ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
                                                     lldb::DynamicValueType use_dynamic,
                                                     TypeAndOrName &class_type_or_name,
                                                     Address &dynamic_address)
{
    // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
    // in the object.  That will point to the "address point" within the vtable (not the beginning of the
    // vtable.)  We can then look up the symbol containing this "address point" and that symbol's name
    // demangled will contain the full class name.
    // The second pointer above the "address point" is the "offset_to_top".  We'll use that to get the
    // start of the value object which holds the dynamic type.
    //

    // Only a pointer or reference type can have a different dynamic and static type:
    if (CouldHaveDynamicValue (in_value))
    {
        // First job, pull out the address at 0 offset from the object.
        AddressType address_type;
        lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
        if (original_ptr == LLDB_INVALID_ADDRESS)
            return false;

        ExecutionContext exe_ctx (in_value.GetExecutionContextRef());

        Target *target = exe_ctx.GetTargetPtr();
        Process *process = exe_ctx.GetProcessPtr();

        char memory_buffer[16];
        DataExtractor data(memory_buffer, sizeof(memory_buffer),
                           process->GetByteOrder(),
                           process->GetAddressByteSize());
        size_t address_byte_size = process->GetAddressByteSize();
        Error error;
        size_t bytes_read = process->ReadMemory (original_ptr,
                                                 memory_buffer,
                                                 address_byte_size,
                                                 error);
        if (!error.Success() || (bytes_read != address_byte_size))
        {
            return false;
        }

        uint32_t offset_ptr = 0;
        lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr);

        if (offset_ptr == 0)
            return false;

        // Now find the symbol that contains this address:

        SymbolContext sc;
        Address address_point_address;
        if (target && !target->GetSectionLoadList().IsEmpty())
        {
            if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
            {
                target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
                Symbol *symbol = sc.symbol;
                if (symbol != NULL)
                {
                    const char *name = symbol->GetMangled().GetDemangledName().AsCString();
                    if (strstr(name, vtable_demangled_prefix) == name)
                    {
                        /*
                        printf ("0x%16.16llx: static-type = '%s' has vtable symbol '%s'\n",
                                original_ptr,
                                in_value.GetTypeName().GetCString(),
                                name);
                        */
                         // We are a C++ class, that's good.  Get the class name and look it up:
                        const char *class_name = name + strlen(vtable_demangled_prefix);
                        class_type_or_name.SetName (class_name);
                        const bool exact_match = true;
                        TypeList class_types;
                        uint32_t num_matches = target->GetImages().FindTypes2 (sc,
                                                                               ConstString(class_name),
                                                                               exact_match,
                                                                               UINT32_MAX,
                                                                               class_types);
                        if (num_matches == 0)
                        {
                            //printf ("0x%16.16llx: is not dynamic\n", original_ptr);
                            return false;
                        }
                        if (num_matches == 1)
                        {
                            lldb::TypeSP type_sp(class_types.GetTypeAtIndex(0));
                            /*
                            printf ("0x%16.16llx: static-type = '%s' has single matching dynamic type: uid={0x%llx}, type-name='%s'\n",
                                    original_ptr,
                                    in_value.GetTypeName().AsCString(),
                                    type_sp->GetID(),
                                    type_sp->GetName().GetCString());
                            */
                            class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
                        }
                        else if (num_matches > 1)
                        {
                            for (size_t i = 0; i < num_matches; i++)
                            {
                                lldb::TypeSP type_sp(class_types.GetTypeAtIndex(i));
                                if (type_sp)
                                {
                                    /*
                                    printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types: uid={0x%llx}, type-name='%s'\n",
                                            original_ptr,
                                            in_value.GetTypeName().AsCString(),
                                            type_sp->GetID(),
                                            type_sp->GetName().GetCString());
                                    */

//                                    if (ClangASTContext::IsCXXClassType(type_sp->GetClangFullType()))
//                                    {
//                                        // There can only be one type with a given name,
//                                        // so we've just found duplicate definitions, and this
//                                        // one will do as well as any other.
//                                        // We don't consider something to have a dynamic type if
//                                        // it is the same as the static type.  So compare against
//                                        // the value we were handed:
//
//                                        clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
//                                        clang::ASTContext *this_ast_ctx = type_sp->GetClangAST ();
//                                        if (in_ast_ctx != this_ast_ctx
//                                            || !ClangASTContext::AreTypesSame (in_ast_ctx,
//                                                                               in_value.GetClangType(),
//                                                                               type_sp->GetClangFullType()))
//                                        {
//                                            class_type_or_name.SetTypeSP (this_type);
//                                            return true;
//                                        }
//                                        return false;
//                                    }
                                }
                            }
                            return false;
                        }

                        // The offset_to_top is two pointers above the address.
                        Address offset_to_top_address = address_point_address;
                        int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
                        offset_to_top_address.Slide (slide);

                        Error error;
                        lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);

                        size_t bytes_read = process->ReadMemory (offset_to_top_location,
                                                                 memory_buffer,
                                                                 address_byte_size,
                                                                 error);

                        if (!error.Success() || (bytes_read != address_byte_size))
                        {
                            return false;
                        }

                        offset_ptr = 0;
                        int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize());

                        // So the dynamic type is a value that starts at offset_to_top
                        // above the original address.
                        lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
                        if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
                        {
                            dynamic_address.SetRawAddress(dynamic_addr);
                        }
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

bool
ItaniumABILanguageRuntime::IsVTableName (const char *name)
{
    if (name == NULL)
        return false;

    // Can we maybe ask Clang about this?
    if (strstr (name, "_vptr$") == name)
        return true;
    else
        return false;
}

//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
LanguageRuntime *
ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
{
    // FIXME: We have to check the process and make sure we actually know that this process supports
    // the Itanium ABI.
    if (language == eLanguageTypeC_plus_plus)
        return new ItaniumABILanguageRuntime (process);
    else
        return NULL;
}

void
ItaniumABILanguageRuntime::Initialize()
{
    PluginManager::RegisterPlugin (pluginName,
                                   pluginDesc,
                                   CreateInstance);
}

void
ItaniumABILanguageRuntime::Terminate()
{
    PluginManager::UnregisterPlugin (CreateInstance);
}

//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
const char *
ItaniumABILanguageRuntime::GetPluginName()
{
    return pluginName;
}

const char *
ItaniumABILanguageRuntime::GetShortPluginName()
{
    return pluginShort;
}

uint32_t
ItaniumABILanguageRuntime::GetPluginVersion()
{
    return 1;
}

static const char *exception_names[] = { "__cxa_begin_catch", "__cxa_throw", "__cxa_rethrow", "__cxa_allocate_exception"};
static const int num_throw_names = 3;
static const int num_expression_throw_names = 1;

BreakpointResolverSP
ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
{
    return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
}

BreakpointResolverSP
ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
{
    BreakpointResolverSP resolver_sp;
    static const int total_expressions = sizeof (exception_names)/sizeof (char *);

    // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
    // anything better with predicting unwinding the expression parser does.  So we have two forms of the exception
    // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
    // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.

    uint32_t num_expressions;
    if (catch_bp && throw_bp)
    {
        if (for_expressions)
            num_expressions = total_expressions;
        else
            num_expressions = total_expressions - num_expression_throw_names;

        resolver_sp.reset (new BreakpointResolverName (bkpt,
                                                       exception_names,
                                                       num_expressions,
                                                       eFunctionNameTypeBase,
                                                       eLazyBoolNo));
    }
    else if (throw_bp)
    {
        if (for_expressions)
            num_expressions = num_throw_names - num_expression_throw_names;
        else
            num_expressions = num_throw_names;

        resolver_sp.reset (new BreakpointResolverName (bkpt,
                                                       exception_names + 1,
                                                       num_expressions,
                                                       eFunctionNameTypeBase,
                                                       eLazyBoolNo));
    }
    else if (catch_bp)
        resolver_sp.reset (new BreakpointResolverName (bkpt,
                                                       exception_names,
                                                       total_expressions - num_throw_names,
                                                       eFunctionNameTypeBase,
                                                       eLazyBoolNo));

    return resolver_sp;
}

void
ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
{
    if (!m_process)
        return;

    const bool catch_bp = false;
    const bool throw_bp = true;
    const bool is_internal = true;
    const bool for_expressions = true;

    // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
    // stop at exception allocation as well.

    if (!m_cxx_exception_bp_sp)
    {
        Target &target = m_process->GetTarget();

        BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
        SearchFilterSP filter_sp = target.GetSearchFilterForModule(NULL);

        m_cxx_exception_bp_sp = target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
    }
    else
        m_cxx_exception_bp_sp->SetEnabled (true);

}

void
ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
{
    if (!m_process)
        return;

    if (m_cxx_exception_bp_sp.get())
    {
        m_cxx_exception_bp_sp->SetEnabled (false);
    }
}

bool
ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{
    if (!m_process)
        return false;

    if (!stop_reason ||
        stop_reason->GetStopReason() != eStopReasonBreakpoint)
        return false;

    uint64_t break_site_id = stop_reason->GetValue();
    return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
                                                                               m_cxx_exception_bp_sp->GetID());

}
<commit_msg>Converted commented out printf statements for dynamic type logging to use the log for "log enabe lldb types".<commit_after>//===-- ItaniumABILanguageRuntime.cpp --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "ItaniumABILanguageRuntime.h"

#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"

#include <vector>

using namespace lldb;
using namespace lldb_private;

static const char *pluginName = "ItaniumABILanguageRuntime";
static const char *pluginDesc = "Itanium ABI for the C++ language";
static const char *pluginShort = "language.itanium";
static const char *vtable_demangled_prefix = "vtable for ";

bool
ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
{
    return in_value.IsPossibleCPlusPlusDynamicType();
}

bool
ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
                                                     lldb::DynamicValueType use_dynamic,
                                                     TypeAndOrName &class_type_or_name,
                                                     Address &dynamic_address)
{
    // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
    // in the object.  That will point to the "address point" within the vtable (not the beginning of the
    // vtable.)  We can then look up the symbol containing this "address point" and that symbol's name
    // demangled will contain the full class name.
    // The second pointer above the "address point" is the "offset_to_top".  We'll use that to get the
    // start of the value object which holds the dynamic type.
    //

    // Only a pointer or reference type can have a different dynamic and static type:
    if (CouldHaveDynamicValue (in_value))
    {
        // First job, pull out the address at 0 offset from the object.
        AddressType address_type;
        lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
        if (original_ptr == LLDB_INVALID_ADDRESS)
            return false;

        ExecutionContext exe_ctx (in_value.GetExecutionContextRef());

        Target *target = exe_ctx.GetTargetPtr();
        Process *process = exe_ctx.GetProcessPtr();

        char memory_buffer[16];
        DataExtractor data(memory_buffer, sizeof(memory_buffer),
                           process->GetByteOrder(),
                           process->GetAddressByteSize());
        size_t address_byte_size = process->GetAddressByteSize();
        Error error;
        size_t bytes_read = process->ReadMemory (original_ptr,
                                                 memory_buffer,
                                                 address_byte_size,
                                                 error);
        if (!error.Success() || (bytes_read != address_byte_size))
        {
            return false;
        }

        uint32_t offset_ptr = 0;
        lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr);

        if (offset_ptr == 0)
            return false;

        // Now find the symbol that contains this address:

        SymbolContext sc;
        Address address_point_address;
        if (target && !target->GetSectionLoadList().IsEmpty())
        {
            if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
            {
                target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
                Symbol *symbol = sc.symbol;
                if (symbol != NULL)
                {
                    const char *name = symbol->GetMangled().GetDemangledName().AsCString();
                    if (strstr(name, vtable_demangled_prefix) == name)
                    {
                        LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
                        if (log)
                            log->Printf ("0x%16.16llx: static-type = '%s' has vtable symbol '%s'\n",
                                         original_ptr,
                                         in_value.GetTypeName().GetCString(),
                                         name);
                        // We are a C++ class, that's good.  Get the class name and look it up:
                        const char *class_name = name + strlen(vtable_demangled_prefix);
                        class_type_or_name.SetName (class_name);
                        const bool exact_match = true;
                        TypeList class_types;
                        uint32_t num_matches = target->GetImages().FindTypes2 (sc,
                                                                               ConstString(class_name),
                                                                               exact_match,
                                                                               UINT32_MAX,
                                                                               class_types);
                        if (num_matches == 0)
                        {
                            if (log)
                                log->Printf("0x%16.16llx: is not dynamic\n", original_ptr);
                            return false;
                        }
                        if (num_matches == 1)
                        {
                            lldb::TypeSP type_sp(class_types.GetTypeAtIndex(0));
                            if (log)
                                log->Printf ("0x%16.16llx: static-type = '%s' has dynamic type: uid={0x%llx}, type-name='%s'\n",
                                             original_ptr,
                                             in_value.GetTypeName().AsCString(),
                                             type_sp->GetID(),
                                             type_sp->GetName().GetCString());

                            class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
                        }
                        else if (num_matches > 1)
                        {
                            for (size_t i = 0; i < num_matches; i++)
                            {
                                lldb::TypeSP type_sp(class_types.GetTypeAtIndex(i));
                                if (type_sp)
                                {
                                    if (log)
                                        log->Printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types: uid={0x%llx}, type-name='%s'\n",
                                                     original_ptr,
                                                     in_value.GetTypeName().AsCString(),
                                                     type_sp->GetID(),
                                                     type_sp->GetName().GetCString());

//                                    if (ClangASTContext::IsCXXClassType(type_sp->GetClangFullType()))
//                                    {
//                                        // There can only be one type with a given name,
//                                        // so we've just found duplicate definitions, and this
//                                        // one will do as well as any other.
//                                        // We don't consider something to have a dynamic type if
//                                        // it is the same as the static type.  So compare against
//                                        // the value we were handed:
//
//                                        clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
//                                        clang::ASTContext *this_ast_ctx = type_sp->GetClangAST ();
//                                        if (in_ast_ctx != this_ast_ctx
//                                            || !ClangASTContext::AreTypesSame (in_ast_ctx,
//                                                                               in_value.GetClangType(),
//                                                                               type_sp->GetClangFullType()))
//                                        {
//                                            class_type_or_name.SetTypeSP (this_type);
//                                            return true;
//                                        }
//                                        return false;
//                                    }
                                }
                            }
                            return false;
                        }

                        // The offset_to_top is two pointers above the address.
                        Address offset_to_top_address = address_point_address;
                        int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
                        offset_to_top_address.Slide (slide);

                        Error error;
                        lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);

                        size_t bytes_read = process->ReadMemory (offset_to_top_location,
                                                                 memory_buffer,
                                                                 address_byte_size,
                                                                 error);

                        if (!error.Success() || (bytes_read != address_byte_size))
                        {
                            return false;
                        }

                        offset_ptr = 0;
                        int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize());

                        // So the dynamic type is a value that starts at offset_to_top
                        // above the original address.
                        lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
                        if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
                        {
                            dynamic_address.SetRawAddress(dynamic_addr);
                        }
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

bool
ItaniumABILanguageRuntime::IsVTableName (const char *name)
{
    if (name == NULL)
        return false;

    // Can we maybe ask Clang about this?
    if (strstr (name, "_vptr$") == name)
        return true;
    else
        return false;
}

//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
LanguageRuntime *
ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
{
    // FIXME: We have to check the process and make sure we actually know that this process supports
    // the Itanium ABI.
    if (language == eLanguageTypeC_plus_plus)
        return new ItaniumABILanguageRuntime (process);
    else
        return NULL;
}

void
ItaniumABILanguageRuntime::Initialize()
{
    PluginManager::RegisterPlugin (pluginName,
                                   pluginDesc,
                                   CreateInstance);
}

void
ItaniumABILanguageRuntime::Terminate()
{
    PluginManager::UnregisterPlugin (CreateInstance);
}

//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
const char *
ItaniumABILanguageRuntime::GetPluginName()
{
    return pluginName;
}

const char *
ItaniumABILanguageRuntime::GetShortPluginName()
{
    return pluginShort;
}

uint32_t
ItaniumABILanguageRuntime::GetPluginVersion()
{
    return 1;
}

static const char *exception_names[] = { "__cxa_begin_catch", "__cxa_throw", "__cxa_rethrow", "__cxa_allocate_exception"};
static const int num_throw_names = 3;
static const int num_expression_throw_names = 1;

BreakpointResolverSP
ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
{
    return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
}

BreakpointResolverSP
ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
{
    BreakpointResolverSP resolver_sp;
    static const int total_expressions = sizeof (exception_names)/sizeof (char *);

    // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
    // anything better with predicting unwinding the expression parser does.  So we have two forms of the exception
    // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
    // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.

    uint32_t num_expressions;
    if (catch_bp && throw_bp)
    {
        if (for_expressions)
            num_expressions = total_expressions;
        else
            num_expressions = total_expressions - num_expression_throw_names;

        resolver_sp.reset (new BreakpointResolverName (bkpt,
                                                       exception_names,
                                                       num_expressions,
                                                       eFunctionNameTypeBase,
                                                       eLazyBoolNo));
    }
    else if (throw_bp)
    {
        if (for_expressions)
            num_expressions = num_throw_names - num_expression_throw_names;
        else
            num_expressions = num_throw_names;

        resolver_sp.reset (new BreakpointResolverName (bkpt,
                                                       exception_names + 1,
                                                       num_expressions,
                                                       eFunctionNameTypeBase,
                                                       eLazyBoolNo));
    }
    else if (catch_bp)
        resolver_sp.reset (new BreakpointResolverName (bkpt,
                                                       exception_names,
                                                       total_expressions - num_throw_names,
                                                       eFunctionNameTypeBase,
                                                       eLazyBoolNo));

    return resolver_sp;
}

void
ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
{
    if (!m_process)
        return;

    const bool catch_bp = false;
    const bool throw_bp = true;
    const bool is_internal = true;
    const bool for_expressions = true;

    // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
    // stop at exception allocation as well.

    if (!m_cxx_exception_bp_sp)
    {
        Target &target = m_process->GetTarget();

        BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
        SearchFilterSP filter_sp = target.GetSearchFilterForModule(NULL);

        m_cxx_exception_bp_sp = target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
    }
    else
        m_cxx_exception_bp_sp->SetEnabled (true);

}

void
ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
{
    if (!m_process)
        return;

    if (m_cxx_exception_bp_sp.get())
    {
        m_cxx_exception_bp_sp->SetEnabled (false);
    }
}

bool
ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{
    if (!m_process)
        return false;

    if (!stop_reason ||
        stop_reason->GetStopReason() != eStopReasonBreakpoint)
        return false;

    uint64_t break_site_id = stop_reason->GetValue();
    return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
                                                                               m_cxx_exception_bp_sp->GetID());

}
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. 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.
==============================================================================*/

#include <functional>
#include <unordered_map>
#include <utility>

#include "tensorflow/core/framework/bounds_check.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/hash/hash.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;

template <typename T, typename TIndex>
class UniqueOp : public OpKernel {
 public:
  explicit UniqueOp(OpKernelConstruction* context) : OpKernel(context) {}

  void Compute(OpKernelContext* context) override {
    const Tensor& input = context->input(0);
    // TODO(dga):  Make unique polymorphic for returning int32 and int64
    // vectors to support large tensors.
    OP_REQUIRES(context,
                input.NumElements() <= std::numeric_limits<int32>::max(),
                errors::InvalidArgument(
                    "unique does not support input tensors larger than ",
                    std::numeric_limits<int32>::max(), " elements"));

    int64 axis = 0;
    std::vector<int64> new_sizes{1, input.NumElements(), 1};
    if (context->num_inputs() == 1) {
      OP_REQUIRES(context, TensorShapeUtils::IsVector(input.shape()),
                  errors::InvalidArgument("unique expects a 1D vector."));
    } else {
      // In case of UniqueV2, the axis is a 1D vector. The purpose is
      // to allow specifying either "no axis" or "axis". The `[]` means
      // "no axis", while `[x]` means `axis = x`.
      const Tensor& axis_tensor = context->input(1);
      OP_REQUIRES(context, TensorShapeUtils::IsVector(axis_tensor.shape()),
                  errors::InvalidArgument("axis expects a 1D vector."));
      OP_REQUIRES(
          context, axis_tensor.NumElements() <= 1,
          errors::InvalidArgument(
              "axis does not support input tensors larger than 1 elements"));
      if (axis_tensor.NumElements() == 0) {
        OP_REQUIRES(context, TensorShapeUtils::IsVector(input.shape()),
                    errors::InvalidArgument("unique expects a 1D vector."));
      } else {
        OP_REQUIRES(context,
                    (axis_tensor.dtype() == DT_INT32 ||
                     axis_tensor.dtype() == DT_INT64),
                    errors::InvalidArgument(
                        "axis tensor should be int32 or int64, but got ",
                        DataTypeString(axis_tensor.dtype())));
        if (axis_tensor.dtype() == DT_INT32) {
          axis = internal::SubtleMustCopy(axis_tensor.scalar<int32>()());
        } else {
          axis = internal::SubtleMustCopy(axis_tensor.scalar<int64>()());
        }
        axis = axis < 0 ? axis + input.dims() : axis;
        OP_REQUIRES(context, 0 <= axis && axis < input.dims(),
                    errors::InvalidArgument("axis has to be between [0, ",
                                            input.dims(), ")"));
        if (axis > 0) {
          for (int64 i = 0; i < axis; i++) {
            new_sizes[0] *= input.dim_size(i);
          }
        }
        new_sizes[1] = input.dim_size(axis);
        if (axis + 1 < input.dims()) {
          for (int64 i = axis + 1; i < input.dims(); i++) {
            new_sizes[2] *= input.dim_size(i);
          }
        }
      }
    }

    Tensor* idx = nullptr;
    OP_REQUIRES_OK(context, context->allocate_output(
                                1, TensorShape({new_sizes[1]}), &idx));
    auto idx_vec = idx->template vec<TIndex>();

    int64 uniq_size;
    if (new_sizes[0] == 1 && new_sizes[2] == 1) {
      // Specialized and faster implementation when unique is run over single
      // elements. Here we put T directly into the map rather than ints pointing
      // to them as in the general case.
      auto Tin = input.flat<T>();
      const int64 N = static_cast<int64>(Tin.size());

      std::unordered_map<T, TIndex> uniq;
      uniq.reserve(2 * N);
      for (Eigen::Index i = 0, j = 0; i < N; ++i) {
        auto it = uniq.insert(std::make_pair(Tin(i), j));
        idx_vec(i) = it.first->second;
        if (it.second) {
          ++j;
        }
      }

      uniq_size = static_cast<int64>(uniq.size());
      TensorShape output_shape(input.shape());
      output_shape.set_dim(axis, uniq_size);
      Tensor* output = nullptr;
      OP_REQUIRES_OK(context,
                     context->allocate_output(0, output_shape, &output));
      auto Tout = output->flat<T>();

      for (auto it : uniq) {
        Tout(it.second) = it.first;
      }
    } else {
      // General implementation when unique is run over multiple elements.
      auto Tin = input.shaped<T, 3>(new_sizes);

      auto hash_fn = [&Tin](const Eigen::Index& key) {
        size_t h = 0;
        for (Eigen::Index i = 0; i < Tin.dimension(0); i++) {
          for (Eigen::Index j = 0; j < Tin.dimension(2); j++) {
            h = Hash64Combine(h, hash<T>{}(Tin(i, key, j)));
          }
        }
        return h;
      };

      auto equal_to_fn = [&Tin](const Eigen::Index& lhs,
                                const Eigen::Index& rhs) {
        for (Eigen::Index i = 0; i < Tin.dimension(0); i++) {
          for (Eigen::Index j = 0; j < Tin.dimension(2); j++) {
            if (Tin(i, lhs, j) != Tin(i, rhs, j)) {
              return false;
            }
          }
        }
        return true;
      };

      std::unordered_map<int64, int64, decltype(hash_fn), decltype(equal_to_fn)>
          uniq(0, hash_fn, equal_to_fn);

      uniq.reserve(2 * Tin.dimension(1));

      for (int64 i = 0, j = 0; i < Tin.dimension(1); ++i) {
        auto it = uniq.insert(std::make_pair(i, j));
        idx_vec(i) = it.first->second;
        if (it.second) {
          ++j;
        }
      }

      uniq_size = static_cast<int64>(uniq.size());
      new_sizes[1] = uniq_size;
      TensorShape output_shape(input.shape());
      output_shape.set_dim(axis, uniq_size);
      Tensor* output = nullptr;
      OP_REQUIRES_OK(context,
                     context->allocate_output(0, output_shape, &output));
      auto Tout = output->shaped<T, 3>(new_sizes);

      for (auto it : uniq) {
        Tout.chip(it.second, 1) = Tin.chip(it.first, 1);
      }
    }

    if (num_outputs() > 2) {
      Tensor* output = nullptr;
      OP_REQUIRES_OK(context, context->allocate_output(
                                  2, TensorShape({uniq_size}), &output));
      auto count_output_vec = output->template vec<TIndex>();
      count_output_vec.setZero();
      const int N = idx_vec.size();
      for (int64 i = 0; i < N; ++i) {
        count_output_vec(idx_vec(i))++;
      }
    }
  }
};

#define REGISTER_UNIQUE(type)                                    \
  REGISTER_KERNEL_BUILDER(Name("Unique")                         \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type, int32>);                \
  REGISTER_KERNEL_BUILDER(Name("Unique")                         \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int64>("out_idx"), \
                          UniqueOp<type, int64>);                \
  REGISTER_KERNEL_BUILDER(Name("UniqueV2")                       \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type, int32>);                \
  REGISTER_KERNEL_BUILDER(Name("UniqueV2")                       \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int64>("out_idx"), \
                          UniqueOp<type, int64>);                \
  REGISTER_KERNEL_BUILDER(Name("UniqueWithCounts")               \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type, int32>)                 \
  REGISTER_KERNEL_BUILDER(Name("UniqueWithCounts")               \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int64>("out_idx"), \
                          UniqueOp<type, int64>);                \
  REGISTER_KERNEL_BUILDER(Name("UniqueWithCountsV2")             \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type, int32>)                 \
  REGISTER_KERNEL_BUILDER(Name("UniqueWithCountsV2")             \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int64>("out_idx"), \
                          UniqueOp<type, int64>)
TF_CALL_REAL_NUMBER_TYPES(REGISTER_UNIQUE);
REGISTER_UNIQUE(string)
#undef REGISTER_UNIQUE

// Fake integer GPU kernels so that the use of Unique in optimizers (to
// de-duplicate sparse gradient indices) does not conflict with gradients being
// located on a GPU. These kernels run on the CPU, their inputs and outputs
// residing in host (not GPU) memory.
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32, int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int64>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32, int64>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64, int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int64>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64, int64>);

#ifdef TENSORFLOW_USE_SYCL
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32, int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64, int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int64>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32, int64>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int64>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64, int64>);
#endif  // TENSORFLOW_USE_SYCL
}  // namespace tensorflow
<commit_msg>Add bool support for unique_with_counts<commit_after>/* Copyright 2015 The TensorFlow Authors. 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.
==============================================================================*/

#include <functional>
#include <unordered_map>
#include <utility>

#include "tensorflow/core/framework/bounds_check.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/hash/hash.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;

template <typename T, typename TIndex>
class UniqueOp : public OpKernel {
 public:
  explicit UniqueOp(OpKernelConstruction* context) : OpKernel(context) {}

  void Compute(OpKernelContext* context) override {
    const Tensor& input = context->input(0);
    // TODO(dga):  Make unique polymorphic for returning int32 and int64
    // vectors to support large tensors.
    OP_REQUIRES(context,
                input.NumElements() <= std::numeric_limits<int32>::max(),
                errors::InvalidArgument(
                    "unique does not support input tensors larger than ",
                    std::numeric_limits<int32>::max(), " elements"));

    int64 axis = 0;
    std::vector<int64> new_sizes{1, input.NumElements(), 1};
    if (context->num_inputs() == 1) {
      OP_REQUIRES(context, TensorShapeUtils::IsVector(input.shape()),
                  errors::InvalidArgument("unique expects a 1D vector."));
    } else {
      // In case of UniqueV2, the axis is a 1D vector. The purpose is
      // to allow specifying either "no axis" or "axis". The `[]` means
      // "no axis", while `[x]` means `axis = x`.
      const Tensor& axis_tensor = context->input(1);
      OP_REQUIRES(context, TensorShapeUtils::IsVector(axis_tensor.shape()),
                  errors::InvalidArgument("axis expects a 1D vector."));
      OP_REQUIRES(
          context, axis_tensor.NumElements() <= 1,
          errors::InvalidArgument(
              "axis does not support input tensors larger than 1 elements"));
      if (axis_tensor.NumElements() == 0) {
        OP_REQUIRES(context, TensorShapeUtils::IsVector(input.shape()),
                    errors::InvalidArgument("unique expects a 1D vector."));
      } else {
        OP_REQUIRES(context,
                    (axis_tensor.dtype() == DT_INT32 ||
                     axis_tensor.dtype() == DT_INT64),
                    errors::InvalidArgument(
                        "axis tensor should be int32 or int64, but got ",
                        DataTypeString(axis_tensor.dtype())));
        if (axis_tensor.dtype() == DT_INT32) {
          axis = internal::SubtleMustCopy(axis_tensor.scalar<int32>()());
        } else {
          axis = internal::SubtleMustCopy(axis_tensor.scalar<int64>()());
        }
        axis = axis < 0 ? axis + input.dims() : axis;
        OP_REQUIRES(context, 0 <= axis && axis < input.dims(),
                    errors::InvalidArgument("axis has to be between [0, ",
                                            input.dims(), ")"));
        if (axis > 0) {
          for (int64 i = 0; i < axis; i++) {
            new_sizes[0] *= input.dim_size(i);
          }
        }
        new_sizes[1] = input.dim_size(axis);
        if (axis + 1 < input.dims()) {
          for (int64 i = axis + 1; i < input.dims(); i++) {
            new_sizes[2] *= input.dim_size(i);
          }
        }
      }
    }

    Tensor* idx = nullptr;
    OP_REQUIRES_OK(context, context->allocate_output(
                                1, TensorShape({new_sizes[1]}), &idx));
    auto idx_vec = idx->template vec<TIndex>();

    int64 uniq_size;
    if (new_sizes[0] == 1 && new_sizes[2] == 1) {
      // Specialized and faster implementation when unique is run over single
      // elements. Here we put T directly into the map rather than ints pointing
      // to them as in the general case.
      auto Tin = input.flat<T>();
      const int64 N = static_cast<int64>(Tin.size());

      std::unordered_map<T, TIndex> uniq;
      uniq.reserve(2 * N);
      for (Eigen::Index i = 0, j = 0; i < N; ++i) {
        auto it = uniq.insert(std::make_pair(Tin(i), j));
        idx_vec(i) = it.first->second;
        if (it.second) {
          ++j;
        }
      }

      uniq_size = static_cast<int64>(uniq.size());
      TensorShape output_shape(input.shape());
      output_shape.set_dim(axis, uniq_size);
      Tensor* output = nullptr;
      OP_REQUIRES_OK(context,
                     context->allocate_output(0, output_shape, &output));
      auto Tout = output->flat<T>();

      for (auto it : uniq) {
        Tout(it.second) = it.first;
      }
    } else {
      // General implementation when unique is run over multiple elements.
      auto Tin = input.shaped<T, 3>(new_sizes);

      auto hash_fn = [&Tin](const Eigen::Index& key) {
        size_t h = 0;
        for (Eigen::Index i = 0; i < Tin.dimension(0); i++) {
          for (Eigen::Index j = 0; j < Tin.dimension(2); j++) {
            h = Hash64Combine(h, hash<T>{}(Tin(i, key, j)));
          }
        }
        return h;
      };

      auto equal_to_fn = [&Tin](const Eigen::Index& lhs,
                                const Eigen::Index& rhs) {
        for (Eigen::Index i = 0; i < Tin.dimension(0); i++) {
          for (Eigen::Index j = 0; j < Tin.dimension(2); j++) {
            if (Tin(i, lhs, j) != Tin(i, rhs, j)) {
              return false;
            }
          }
        }
        return true;
      };

      std::unordered_map<int64, int64, decltype(hash_fn), decltype(equal_to_fn)>
          uniq(0, hash_fn, equal_to_fn);

      uniq.reserve(2 * Tin.dimension(1));

      for (int64 i = 0, j = 0; i < Tin.dimension(1); ++i) {
        auto it = uniq.insert(std::make_pair(i, j));
        idx_vec(i) = it.first->second;
        if (it.second) {
          ++j;
        }
      }

      uniq_size = static_cast<int64>(uniq.size());
      new_sizes[1] = uniq_size;
      TensorShape output_shape(input.shape());
      output_shape.set_dim(axis, uniq_size);
      Tensor* output = nullptr;
      OP_REQUIRES_OK(context,
                     context->allocate_output(0, output_shape, &output));
      auto Tout = output->shaped<T, 3>(new_sizes);

      for (auto it : uniq) {
        Tout.chip(it.second, 1) = Tin.chip(it.first, 1);
      }
    }

    if (num_outputs() > 2) {
      Tensor* output = nullptr;
      OP_REQUIRES_OK(context, context->allocate_output(
                                  2, TensorShape({uniq_size}), &output));
      auto count_output_vec = output->template vec<TIndex>();
      count_output_vec.setZero();
      const int N = idx_vec.size();
      for (int64 i = 0; i < N; ++i) {
        count_output_vec(idx_vec(i))++;
      }
    }
  }
};

#define REGISTER_UNIQUE(type)                                    \
  REGISTER_KERNEL_BUILDER(Name("Unique")                         \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type, int32>);                \
  REGISTER_KERNEL_BUILDER(Name("Unique")                         \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int64>("out_idx"), \
                          UniqueOp<type, int64>);                \
  REGISTER_KERNEL_BUILDER(Name("UniqueV2")                       \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type, int32>);                \
  REGISTER_KERNEL_BUILDER(Name("UniqueV2")                       \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int64>("out_idx"), \
                          UniqueOp<type, int64>);                \
  REGISTER_KERNEL_BUILDER(Name("UniqueWithCounts")               \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type, int32>)                 \
  REGISTER_KERNEL_BUILDER(Name("UniqueWithCounts")               \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int64>("out_idx"), \
                          UniqueOp<type, int64>);                \
  REGISTER_KERNEL_BUILDER(Name("UniqueWithCountsV2")             \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int32>("out_idx"), \
                          UniqueOp<type, int32>)                 \
  REGISTER_KERNEL_BUILDER(Name("UniqueWithCountsV2")             \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<type>("T")         \
                              .TypeConstraint<int64>("out_idx"), \
                          UniqueOp<type, int64>)
TF_CALL_REAL_NUMBER_TYPES(REGISTER_UNIQUE);
REGISTER_UNIQUE(string)
REGISTER_UNIQUE(bool)
#undef REGISTER_UNIQUE

// Fake integer GPU kernels so that the use of Unique in optimizers (to
// de-duplicate sparse gradient indices) does not conflict with gradients being
// located on a GPU. These kernels run on the CPU, their inputs and outputs
// residing in host (not GPU) memory.
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32, int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int64>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32, int64>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64, int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int64>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64, int64>);

#ifdef TENSORFLOW_USE_SYCL
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32, int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int32>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64, int32>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int32>("T")
                            .TypeConstraint<int64>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int32, int64>);
REGISTER_KERNEL_BUILDER(Name("Unique")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int64>("T")
                            .TypeConstraint<int64>("out_idx")
                            .HostMemory("x")
                            .HostMemory("y")
                            .HostMemory("idx"),
                        UniqueOp<int64, int64>);
#endif  // TENSORFLOW_USE_SYCL
}  // namespace tensorflow
<|endoftext|>


<commit_before>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2017 Igor Petrovic

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "Database.h"
#include "../board/Board.h"

///
/// \brief Creates database layout by defining blocks and sections.
///
void Database::createLayout()
{
    DBMS::addBlocks(DB_BLOCKS);

    dbSection_t section;

    {
        section.parameters = MIDI_FEATURES;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_MIDI, section);

        section.parameters = MIDI_CHANNELS;
        section.defaultValue = 1;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_MIDI, section);
    }

    {
        section.parameters = MAX_NUMBER_OF_BUTTONS+MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_BUTTON, section);

        section.parameters = MAX_NUMBER_OF_BUTTONS+MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_BUTTON, section);

        section.parameters = MAX_NUMBER_OF_BUTTONS+MAX_NUMBER_OF_ANALOG;
        section.defaultValue = AUTO_INCREMENT;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_BUTTON, section);
    }

    {
        section.parameters = MAX_NUMBER_OF_ENCODERS;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ENCODER, section);

        section.parameters = MAX_NUMBER_OF_ENCODERS;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ENCODER, section);

        section.parameters = MAX_NUMBER_OF_ENCODERS;
        section.defaultValue = 0;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ENCODER, section);

        section.parameters = MAX_NUMBER_OF_ENCODERS;
        section.defaultValue = AUTO_INCREMENT;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ENCODER, section);
    }

    {
        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);

        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);

        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);

        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = AUTO_INCREMENT;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);

        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);

        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 127;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);
    }

    {
        section.parameters = LED_HARDWARE_PARAMETERS;
        section.defaultValue = 0;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_LED, section);

        section.parameters = MAX_NUMBER_OF_LEDS;
        section.defaultValue = AUTO_INCREMENT;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_LED, section);

        section.parameters = MAX_NUMBER_OF_LEDS;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_LED, section);

        section.parameters = MAX_NUMBER_OF_LEDS;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_LED, section);
    }

    {
        section.parameters = ID_OFFSET;
        section.defaultValue = UNIQUE_ID;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ID, section);
    }
}
<commit_msg>add comments<commit_after>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2017 Igor Petrovic

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "Database.h"
#include "../board/Board.h"

///
/// \brief Creates database layout by defining blocks and sections.
///
void Database::createLayout()
{
    DBMS::addBlocks(DB_BLOCKS);

    dbSection_t section;

    {
        //MIDI block

        //midi feature section
        section.parameters = MIDI_FEATURES;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_MIDI, section);

        //midi channel section
        section.parameters = MIDI_CHANNELS;
        section.defaultValue = 1;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_MIDI, section);
    }

    {
        //button block

        //type section
        section.parameters = MAX_NUMBER_OF_BUTTONS+MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_BUTTON, section);

        //program change enabled section
        section.parameters = MAX_NUMBER_OF_BUTTONS+MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_BUTTON, section);

        //midi id section
        section.parameters = MAX_NUMBER_OF_BUTTONS+MAX_NUMBER_OF_ANALOG;
        section.defaultValue = AUTO_INCREMENT;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_BUTTON, section);
    }

    {
        //encoder block

        //encoder enabled section
        section.parameters = MAX_NUMBER_OF_ENCODERS;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ENCODER, section);

        //encoder inverted section
        section.parameters = MAX_NUMBER_OF_ENCODERS;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ENCODER, section);

        //encoding mode section
        section.parameters = MAX_NUMBER_OF_ENCODERS;
        section.defaultValue = 0;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ENCODER, section);

        //midi id section
        section.parameters = MAX_NUMBER_OF_ENCODERS;
        section.defaultValue = AUTO_INCREMENT;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ENCODER, section);
    }

    {
        //analog block

        //analog enabled section
        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);

        //analog inverted section
        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);

        //analog type section
        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);

        //midi id section
        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = AUTO_INCREMENT;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);

        //lower cc limit
        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 0;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);

        //upper cc limit
        section.parameters = MAX_NUMBER_OF_ANALOG;
        section.defaultValue = 127;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ANALOG, section);
    }

    {
        //led block

        //hardware parameters section
        section.parameters = LED_HARDWARE_PARAMETERS;
        section.defaultValue = 0;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_LED, section);

        //activation id section
        section.parameters = MAX_NUMBER_OF_LEDS;
        section.defaultValue = AUTO_INCREMENT;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_LED, section);

        //rgb enabled section
        section.parameters = MAX_NUMBER_OF_LEDS;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_LED, section);

        //local led control enabled section
        section.parameters = MAX_NUMBER_OF_LEDS;
        section.defaultValue = 0;
        section.parameterType = BIT_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_LED, section);
    }

    {
        //ID block

        section.parameters = ID_OFFSET;
        section.defaultValue = UNIQUE_ID;
        section.parameterType = BYTE_PARAMETER;
        section.preserveOnPartialReset = 0;

        DBMS::addSection(DB_BLOCK_ID, section);
    }
}
<|endoftext|>