<commit_before>/*
   Copyright 2014 Brain Research Institute, Melbourne, Australia

   Written by David Raffelt 2014.

   This file is part of MRtrix.

   MRtrix 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.

   MRtrix 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 MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "gui/mrview/tool/fixel.h"

namespace MR
{
  namespace GUI
  {
    namespace MRView
    {
      namespace Tool
      {

        Fixel::Fixel (const std::string& filename, Vector& fixel_tool) :
          Displayable (filename),
          filename (filename),
          fixel_tool (fixel_tool),
          header (filename),
          fixel_data (header),
          fixel_vox (fixel_data),
          header_transform (fixel_vox),
          colourbar_position_index (4),
          slice_fixel_indices (3),
          slice_fixel_sizes (3),
          slice_fixel_counts (3),
          line_length_multiplier (1.0),
          scale_line_length_by_value (false),
          color_type (Value),
          show_colour_bar (true)
          {
            set_allowed_features (true, true, false);
            colourmap = 1;
            alpha = 1.0f;
            set_use_transparency (true);
            colour[0] = colour[1] = colour[2] = 1;
            line_length = 0.45 * static_cast<float>(fixel_vox.vox(0) + fixel_vox.vox(1) + fixel_vox.vox(2)) / 3.0;
            value_min = std::numeric_limits<float>::infinity();
            value_max = -std::numeric_limits<float>::infinity();
            load_image();
          }

        Fixel::~Fixel()
        {
          if (vertex_buffer)
            gl::DeleteBuffers (1, &vertex_buffer);
          if (vertex_array_object)
            gl::DeleteVertexArrays (1, &vertex_array_object);
          if (value_buffer)
            gl::DeleteBuffers (1, &value_buffer);
          if (value_array_object)
            gl::DeleteBuffers (1, &value_array_object);
        }

        std::string Fixel::Shader::vertex_shader_source (const Displayable& fixel)
        {
           std::string source =
               "layout (location = 0) in vec3 pos;\n"
               "layout (location = 1) in vec3 prev;\n"
               "layout (location = 2) in vec3 next;\n"
               "layout (location = 3) in float value;\n"
               "uniform mat4 MVP;\n"
               "uniform float line_length;\n"
               "uniform float max_value;\n"
               "uniform bool scale_line_length_by_value;\n"
               "flat out float value_out;\n"
               "out vec3 fragmentColour;\n";

           switch (color_type) {
             case Direction: break;
             case Colour:
               source += "uniform vec3 const_colour;\n";
               break;
             case Value:
               source += "uniform float offset, scale;\n";
               break;
           }

           source +=
               "void main() {\n"
               "  vec3 centre = pos;\n"
               "  vec3 dir = next;\n"
               "  if ((gl_VertexID % 2) > 0) {\n"
               "    centre = prev;\n"
               "    dir = -pos;\n"
               "  }\n"
               "  value_out = value;\n"
               "  if (scale_line_length_by_value)\n"
               "    gl_Position =  MVP * vec4 (centre + line_length * value * dir,1);\n"
               "  else\n"
               "    gl_Position =  MVP * vec4 (centre + line_length * dir,1);\n";

           switch (color_type) {
             case Colour:
               source +=
                   "  fragmentColour = const_colour;\n";
               break;
             case Value:
               if (!ColourMap::maps[colourmap].special) {
                 source += "  float amplitude = clamp (";
                 if (fixel.scale_inverted())
                   source += "1.0 -";
                 source += " scale * (value_out - offset), 0.0, 1.0);\n";
               }
               source +=
                 std::string ("  vec3 color;\n") +
                 ColourMap::maps[colourmap].mapping +
                 "  fragmentColour = color;\n";
               break;
             case Direction:
               source +=
                 "  fragmentColour = normalize (abs (dir));\n";
               break;
             default:
               break;
           }
           source += "}\n";
           return source;
        }

        std::string Fixel::Shader::fragment_shader_source (const Displayable& fixel)
        {
          std::string source =
              "in float include; \n"
              "out vec3 color;\n"
              "flat in float value_out;\n"
              "in vec3 fragmentColour;\n";

          if (fixel.use_discard_lower())
            source += "uniform float lower;\n";
          if (fixel.use_discard_upper())
            source += "uniform float upper;\n";

          source +=
              "void main(){\n";

          if (fixel.use_discard_lower())
            source += "  if (value_out < lower) discard;\n";
          if (fixel.use_discard_upper())
            source += "  if (value_out > upper) discard;\n";

          source +=
            std::string("  color = fragmentColour;\n");

          source += "}\n";
          return source;
        }

        bool Fixel::Shader::need_update (const Displayable& object) const
        {
          const Fixel& fixel (dynamic_cast<const Fixel&> (object));
          if (color_type != fixel.color_type)
            return true;
          return Displayable::Shader::need_update (object);
        }

        void Fixel::Shader::update (const Displayable& object)
        {
          const Fixel& fixel (dynamic_cast<const Fixel&> (object));
          do_crop_to_slice = fixel.fixel_tool.do_crop_to_slice;
          color_type = fixel.color_type;
          Displayable::Shader::update (object);
        }

        void Fixel::render (const Projection& projection, int axis, int slice)
        {
          start (fixel_shader);
          projection.set (fixel_shader);

          gl::Uniform1f (gl::GetUniformLocation (fixel_shader, "line_length"),
                         line_length * line_length_multiplier);
          gl::Uniform1f (gl::GetUniformLocation (fixel_shader, "max_value"), value_max);
          gl::Uniform1f (gl::GetUniformLocation (fixel_shader, "scale_line_length_by_value"),
                         scale_line_length_by_value);

          if (use_discard_lower())
            gl::Uniform1f (gl::GetUniformLocation (fixel_shader, "lower"), lessthan);
          if (use_discard_upper())
            gl::Uniform1f (gl::GetUniformLocation (fixel_shader, "upper"), greaterthan);

          if (color_type == Colour)
            gl::Uniform3fv (gl::GetUniformLocation (fixel_shader, "const_colour"), 1, colour);

          if (fixel_tool.line_opacity < 1.0) {
            gl::Enable (gl::BLEND);
            gl::Disable (gl::DEPTH_TEST);
            gl::DepthMask (gl::FALSE_);
            gl::BlendEquation (gl::FUNC_ADD);
            gl::BlendFunc (gl::CONSTANT_ALPHA, gl::ONE);
            gl::BlendColor (1.0, 1.0, 1.0, fixel_tool.line_opacity);
          } else {
            gl::Disable (gl::BLEND);
            gl::Enable (gl::DEPTH_TEST);
            gl::DepthMask (gl::TRUE_);
          }

          gl::LineWidth (fixel_tool.line_thickness);

          gl::BindVertexArray (vertex_array_object);

          if (!fixel_tool.do_crop_to_slice) {
            for (size_t x = 0; x < slice_fixel_indices[0].size(); ++x)
              gl::MultiDrawArrays (gl::LINES, &slice_fixel_indices[0][x][0], &slice_fixel_sizes[0][x][0], slice_fixel_counts[0][x]);
          } else {
            gl::MultiDrawArrays (gl::LINES, &slice_fixel_indices[axis][slice][0], &slice_fixel_sizes[axis][slice][0], slice_fixel_counts[axis][slice]);
          }

          if (fixel_tool.line_opacity < 1.0) {
            gl::Disable (gl::BLEND);
            gl::Enable (gl::DEPTH_TEST);
            gl::DepthMask (gl::TRUE_);
          }

          stop (fixel_shader);
        }

        void Fixel::load_image ()
        {
          for (size_t dim = 0; dim < 3; ++dim) {
            slice_fixel_indices[dim].resize (fixel_vox.dim(dim));
            slice_fixel_sizes[dim].resize (fixel_vox.dim(dim));
            slice_fixel_counts[dim].resize (fixel_vox.dim(dim), 0);
          }

          MR::Image::LoopInOrder loop (fixel_vox);
          std::vector<Point<float> > buffer_dir;
          std::vector<float> buffer_val;
          buffer_dir.push_back(Point<float>());
          buffer_val.push_back(NAN);
          Point<float> voxel_pos;
          for (loop.start (fixel_vox); loop.ok(); loop.next (fixel_vox)) {
            for (size_t f = 0; f != fixel_vox.value().size(); ++f) {
              if (fixel_vox.value()[f].value > value_max)
                value_max = fixel_vox.value()[f].value;
              if (fixel_vox.value()[f].value < value_min)
                value_min = fixel_vox.value()[f].value;
              for (size_t dim = 0; dim < 3; ++dim) {
                slice_fixel_indices[dim][fixel_vox[dim]].push_back (buffer_dir.size() - 1);
                slice_fixel_sizes[dim][fixel_vox[dim]].push_back(2);
                slice_fixel_counts[dim][fixel_vox[dim]]++;
              }
              header_transform.voxel2scanner (fixel_vox, voxel_pos);
              buffer_dir.push_back (voxel_pos);
              buffer_dir.push_back (fixel_vox.value()[f].dir);
              buffer_val.push_back (fixel_vox.value()[f].value);
              buffer_val.push_back (fixel_vox.value()[f].value);
            }
          }
          buffer_dir.push_back (Point<float>());
          buffer_val.push_back (NAN);
          this->set_windowing (value_min, value_max);
          greaterthan = value_max;
          lessthan = value_min;

          // voxel centres and fixel directions
          gl::GenBuffers (1, &vertex_buffer);
          gl::BindBuffer (gl::ARRAY_BUFFER, vertex_buffer);
          gl::BufferData (gl::ARRAY_BUFFER, buffer_dir.size() * sizeof(Point<float>), &buffer_dir[0][0], gl::STATIC_DRAW);
          gl::GenVertexArrays (1, &vertex_array_object);
          gl::BindVertexArray (vertex_array_object);
          gl::EnableVertexAttribArray (0);
          gl::VertexAttribPointer (0, 3, gl::FLOAT, gl::FALSE_, 0, (void*)(3*sizeof(float)));
          gl::EnableVertexAttribArray (1);
          gl::VertexAttribPointer (1, 3, gl::FLOAT, gl::FALSE_, 0, (void*)0);
          gl::EnableVertexAttribArray (2);
          gl::VertexAttribPointer (2, 3, gl::FLOAT, gl::FALSE_, 0, (void*)(6*sizeof(float)));

          // fixel values
          gl::GenBuffers (1, &value_buffer);
          gl::BindBuffer (gl::ARRAY_BUFFER, value_buffer);
          gl::BufferData (gl::ARRAY_BUFFER, buffer_val.size() * sizeof(float), &buffer_val[0], gl::STATIC_DRAW);
          gl::EnableVertexAttribArray (3);
          gl::VertexAttribPointer (3, 1, gl::FLOAT, gl::FALSE_, 0, (void*)(sizeof(float)));
        }
      }
    }
  }
}
<commit_msg>Fixed seg fault when vector plot overlay tried to render slice outside of the image<commit_after>/*
   Copyright 2014 Brain Research Institute, Melbourne, Australia

   Written by David Raffelt 2014.

   This file is part of MRtrix.

   MRtrix 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.

   MRtrix 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 MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "gui/mrview/tool/fixel.h"

namespace MR
{
  namespace GUI
  {
    namespace MRView
    {
      namespace Tool
      {

        Fixel::Fixel (const std::string& filename, Vector& fixel_tool) :
          Displayable (filename),
          filename (filename),
          fixel_tool (fixel_tool),
          header (filename),
          fixel_data (header),
          fixel_vox (fixel_data),
          header_transform (fixel_vox),
          colourbar_position_index (4),
          slice_fixel_indices (3),
          slice_fixel_sizes (3),
          slice_fixel_counts (3),
          line_length_multiplier (1.0),
          scale_line_length_by_value (false),
          color_type (Value),
          show_colour_bar (true)
          {
            set_allowed_features (true, true, false);
            colourmap = 1;
            alpha = 1.0f;
            set_use_transparency (true);
            colour[0] = colour[1] = colour[2] = 1;
            line_length = 0.45 * static_cast<float>(fixel_vox.vox(0) + fixel_vox.vox(1) + fixel_vox.vox(2)) / 3.0;
            value_min = std::numeric_limits<float>::infinity();
            value_max = -std::numeric_limits<float>::infinity();
            load_image();
          }

        Fixel::~Fixel()
        {
          if (vertex_buffer)
            gl::DeleteBuffers (1, &vertex_buffer);
          if (vertex_array_object)
            gl::DeleteVertexArrays (1, &vertex_array_object);
          if (value_buffer)
            gl::DeleteBuffers (1, &value_buffer);
          if (value_array_object)
            gl::DeleteBuffers (1, &value_array_object);
        }

        std::string Fixel::Shader::vertex_shader_source (const Displayable& fixel)
        {
           std::string source =
               "layout (location = 0) in vec3 pos;\n"
               "layout (location = 1) in vec3 prev;\n"
               "layout (location = 2) in vec3 next;\n"
               "layout (location = 3) in float value;\n"
               "uniform mat4 MVP;\n"
               "uniform float line_length;\n"
               "uniform float max_value;\n"
               "uniform bool scale_line_length_by_value;\n"
               "flat out float value_out;\n"
               "out vec3 fragmentColour;\n";

           switch (color_type) {
             case Direction: break;
             case Colour:
               source += "uniform vec3 const_colour;\n";
               break;
             case Value:
               source += "uniform float offset, scale;\n";
               break;
           }

           source +=
               "void main() {\n"
               "  vec3 centre = pos;\n"
               "  vec3 dir = next;\n"
               "  if ((gl_VertexID % 2) > 0) {\n"
               "    centre = prev;\n"
               "    dir = -pos;\n"
               "  }\n"
               "  value_out = value;\n"
               "  if (scale_line_length_by_value)\n"
               "    gl_Position =  MVP * vec4 (centre + line_length * value * dir,1);\n"
               "  else\n"
               "    gl_Position =  MVP * vec4 (centre + line_length * dir,1);\n";

           switch (color_type) {
             case Colour:
               source +=
                   "  fragmentColour = const_colour;\n";
               break;
             case Value:
               if (!ColourMap::maps[colourmap].special) {
                 source += "  float amplitude = clamp (";
                 if (fixel.scale_inverted())
                   source += "1.0 -";
                 source += " scale * (value_out - offset), 0.0, 1.0);\n";
               }
               source +=
                 std::string ("  vec3 color;\n") +
                 ColourMap::maps[colourmap].mapping +
                 "  fragmentColour = color;\n";
               break;
             case Direction:
               source +=
                 "  fragmentColour = normalize (abs (dir));\n";
               break;
             default:
               break;
           }
           source += "}\n";
           return source;
        }

        std::string Fixel::Shader::fragment_shader_source (const Displayable& fixel)
        {
          std::string source =
              "in float include; \n"
              "out vec3 color;\n"
              "flat in float value_out;\n"
              "in vec3 fragmentColour;\n";

          if (fixel.use_discard_lower())
            source += "uniform float lower;\n";
          if (fixel.use_discard_upper())
            source += "uniform float upper;\n";

          source +=
              "void main(){\n";

          if (fixel.use_discard_lower())
            source += "  if (value_out < lower) discard;\n";
          if (fixel.use_discard_upper())
            source += "  if (value_out > upper) discard;\n";

          source +=
            std::string("  color = fragmentColour;\n");

          source += "}\n";
          return source;
        }

        bool Fixel::Shader::need_update (const Displayable& object) const
        {
          const Fixel& fixel (dynamic_cast<const Fixel&> (object));
          if (color_type != fixel.color_type)
            return true;
          return Displayable::Shader::need_update (object);
        }

        void Fixel::Shader::update (const Displayable& object)
        {
          const Fixel& fixel (dynamic_cast<const Fixel&> (object));
          do_crop_to_slice = fixel.fixel_tool.do_crop_to_slice;
          color_type = fixel.color_type;
          Displayable::Shader::update (object);
        }

        void Fixel::render (const Projection& projection, int axis, int slice)
        {

          if (fixel_tool.do_crop_to_slice && (slice < 0 || slice >= header.dim(axis)))
            return;

          start (fixel_shader);
          projection.set (fixel_shader);

          gl::Uniform1f (gl::GetUniformLocation (fixel_shader, "line_length"),
                         line_length * line_length_multiplier);
          gl::Uniform1f (gl::GetUniformLocation (fixel_shader, "max_value"), value_max);
          gl::Uniform1f (gl::GetUniformLocation (fixel_shader, "scale_line_length_by_value"),
                         scale_line_length_by_value);

          if (use_discard_lower())
            gl::Uniform1f (gl::GetUniformLocation (fixel_shader, "lower"), lessthan);
          if (use_discard_upper())
            gl::Uniform1f (gl::GetUniformLocation (fixel_shader, "upper"), greaterthan);

          if (color_type == Colour)
            gl::Uniform3fv (gl::GetUniformLocation (fixel_shader, "const_colour"), 1, colour);

          if (fixel_tool.line_opacity < 1.0) {
            gl::Enable (gl::BLEND);
            gl::Disable (gl::DEPTH_TEST);
            gl::DepthMask (gl::FALSE_);
            gl::BlendEquation (gl::FUNC_ADD);
            gl::BlendFunc (gl::CONSTANT_ALPHA, gl::ONE);
            gl::BlendColor (1.0, 1.0, 1.0, fixel_tool.line_opacity);
          } else {
            gl::Disable (gl::BLEND);
            gl::Enable (gl::DEPTH_TEST);
            gl::DepthMask (gl::TRUE_);
          }

          gl::LineWidth (fixel_tool.line_thickness);

          gl::BindVertexArray (vertex_array_object);

          if (!fixel_tool.do_crop_to_slice) {
            for (size_t x = 0; x < slice_fixel_indices[0].size(); ++x)
              gl::MultiDrawArrays (gl::LINES, &slice_fixel_indices[0][x][0], &slice_fixel_sizes[0][x][0], slice_fixel_counts[0][x]);
          } else {
            gl::MultiDrawArrays (gl::LINES, &slice_fixel_indices[axis][slice][0], &slice_fixel_sizes[axis][slice][0], slice_fixel_counts[axis][slice]);
          }

          if (fixel_tool.line_opacity < 1.0) {
            gl::Disable (gl::BLEND);
            gl::Enable (gl::DEPTH_TEST);
            gl::DepthMask (gl::TRUE_);
          }

          stop (fixel_shader);
        }

        void Fixel::load_image ()
        {
          for (size_t dim = 0; dim < 3; ++dim) {
            slice_fixel_indices[dim].resize (fixel_vox.dim(dim));
            slice_fixel_sizes[dim].resize (fixel_vox.dim(dim));
            slice_fixel_counts[dim].resize (fixel_vox.dim(dim), 0);
          }

          MR::Image::LoopInOrder loop (fixel_vox);
          std::vector<Point<float> > buffer_dir;
          std::vector<float> buffer_val;
          buffer_dir.push_back(Point<float>());
          buffer_val.push_back(NAN);
          Point<float> voxel_pos;
          for (loop.start (fixel_vox); loop.ok(); loop.next (fixel_vox)) {
            for (size_t f = 0; f != fixel_vox.value().size(); ++f) {
              if (fixel_vox.value()[f].value > value_max)
                value_max = fixel_vox.value()[f].value;
              if (fixel_vox.value()[f].value < value_min)
                value_min = fixel_vox.value()[f].value;
              for (size_t dim = 0; dim < 3; ++dim) {
                slice_fixel_indices[dim][fixel_vox[dim]].push_back (buffer_dir.size() - 1);
                slice_fixel_sizes[dim][fixel_vox[dim]].push_back(2);
                slice_fixel_counts[dim][fixel_vox[dim]]++;
              }
              header_transform.voxel2scanner (fixel_vox, voxel_pos);
              buffer_dir.push_back (voxel_pos);
              buffer_dir.push_back (fixel_vox.value()[f].dir);
              buffer_val.push_back (fixel_vox.value()[f].value);
              buffer_val.push_back (fixel_vox.value()[f].value);
            }
          }
          buffer_dir.push_back (Point<float>());
          buffer_val.push_back (NAN);
          this->set_windowing (value_min, value_max);
          greaterthan = value_max;
          lessthan = value_min;

          // voxel centres and fixel directions
          gl::GenBuffers (1, &vertex_buffer);
          gl::BindBuffer (gl::ARRAY_BUFFER, vertex_buffer);
          gl::BufferData (gl::ARRAY_BUFFER, buffer_dir.size() * sizeof(Point<float>), &buffer_dir[0][0], gl::STATIC_DRAW);
          gl::GenVertexArrays (1, &vertex_array_object);
          gl::BindVertexArray (vertex_array_object);
          gl::EnableVertexAttribArray (0);
          gl::VertexAttribPointer (0, 3, gl::FLOAT, gl::FALSE_, 0, (void*)(3*sizeof(float)));
          gl::EnableVertexAttribArray (1);
          gl::VertexAttribPointer (1, 3, gl::FLOAT, gl::FALSE_, 0, (void*)0);
          gl::EnableVertexAttribArray (2);
          gl::VertexAttribPointer (2, 3, gl::FLOAT, gl::FALSE_, 0, (void*)(6*sizeof(float)));

          // fixel values
          gl::GenBuffers (1, &value_buffer);
          gl::BindBuffer (gl::ARRAY_BUFFER, value_buffer);
          gl::BufferData (gl::ARRAY_BUFFER, buffer_val.size() * sizeof(float), &buffer_val[0], gl::STATIC_DRAW);
          gl::EnableVertexAttribArray (3);
          gl::VertexAttribPointer (3, 1, gl::FLOAT, gl::FALSE_, 0, (void*)(sizeof(float)));
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>/*
Resembla: Word-based Japanese similar sentence search library
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef __HIERARCHICAL_RESEMBLA_HPP__
#define __HIERARCHICAL_RESEMBLA_HPP__

#include <string>
#include <vector>
#include <memory>
#include <fstream>

#include <resembla/resembla_interface.hpp>
#include <resembla/reranker.hpp>

namespace resembla {

template<class Preprocessor, class ScoreFunction>
class HierarchicalResembla: public ResemblaInterface
{
public:
    HierarchicalResembla(std::shared_ptr<ResemblaInterface> resembla, size_t max_candidate,
            std::shared_ptr<Preprocessor> preprocess, std::shared_ptr<ScoreFunction> score_func,
            const std::string corpus_path = "", int col = 2):
        resembla(resembla), max_candidate(max_candidate),
        preprocess(preprocess), score_func(score_func), reranker(), preprocess_corpus(!corpus_path.empty())
    {
        if(preprocess_corpus){
            loadCorpusFeatures(corpus_path, col);
        }
    }

    std::vector<ResemblaInterface::response_type> getSimilarTexts(
            const string_type& input, size_t max_response, double threshold)
    {
        // extract candidates using original resembla
        std::vector<WorkData> candidates;
        auto original_results = resembla->getSimilarTexts(input, max_candidate, threshold);
        for(const auto& original_result: original_results){
            if(preprocess_corpus){
                candidates.push_back(std::make_pair(original_result.text, (*preprocess)(original_result, corpus_features[original_result.text])));
            }
            else{
                candidates.push_back(std::make_pair(original_result.text, (*preprocess)(original_result)));
            }
        }

        // rerank by its own metric
        WorkData input_data = std::make_pair(input, (*preprocess)(input));
        auto reranked = reranker.rerank(input_data, std::begin(candidates), std::end(candidates), *score_func);

        std::vector<ResemblaInterface::response_type> results;
        for(const auto& r: reranked){
            if(r.second < threshold || results.size() >= max_response){
                break;
            }
            results.push_back({r.first, score_func->name, r.second});
        }
        return results;
    }

protected:
    using WorkData = std::pair<string_type, typename Preprocessor::return_type>;

    const std::shared_ptr<ResemblaInterface> resembla;
    const size_t max_candidate;

    const std::shared_ptr<Preprocessor> preprocess;
    const std::shared_ptr<ScoreFunction> score_func;
    const Reranker<string_type> reranker;

    bool preprocess_corpus;

    void loadCorpusFeatures(const std::string& corpus_path, size_t col)
    {
        std::ifstream ifs(corpus_path);
        if(ifs.fail()){
            throw std::runtime_error("input file is not available: " + corpus_path);
        }
        while(ifs.good()){
            std::string line;
            std::getline(ifs, line);
            if(ifs.eof() || line.length() == 0){
                break;
            }
            auto columns = split(line, '\t');
            if(columns.size() + 1 < col){
                continue;
            }
            corpus_features[cast_string<string_type>(columns[0])] = (*preprocess)(columns[0], columns[1]);
        }
    }

    std::unordered_map<string_type, typename Preprocessor::return_type> corpus_features;
};

}
#endif
<commit_msg>improve code<commit_after>/*
Resembla: Word-based Japanese similar sentence search library
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef __HIERARCHICAL_RESEMBLA_HPP__
#define __HIERARCHICAL_RESEMBLA_HPP__

#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include <fstream>

#include <resembla/resembla_interface.hpp>
#include <resembla/reranker.hpp>

namespace resembla {

template<class Preprocessor, class ScoreFunction>
class HierarchicalResembla: public ResemblaInterface
{
public:
    HierarchicalResembla(std::shared_ptr<ResemblaInterface> resembla, size_t max_candidate,
            std::shared_ptr<Preprocessor> preprocess, std::shared_ptr<ScoreFunction> score_func,
            std::string corpus_path = "", size_t col = 2):
        resembla(resembla), max_candidate(max_candidate),
        preprocess(preprocess), score_func(score_func), reranker(), preprocess_corpus(!corpus_path.empty())
    {
        if(preprocess_corpus){
            loadCorpusFeatures(corpus_path, col);
        }
    }

    std::vector<ResemblaInterface::response_type> getSimilarTexts(
            const string_type& input, size_t max_response, double threshold)
    {
        // extract candidates using original resembla
        std::vector<WorkData> candidates;
        auto original_results = resembla->getSimilarTexts(input, max_candidate, threshold);
        for(const auto& original_result: original_results){
            candidates.push_back(std::make_pair(original_result.text, preprocess_corpus ?
                    (*preprocess)(original_result, corpus_features[original_result.text]) :
                    (*preprocess)(original_result)));
        }

        // rerank by its own metric
        WorkData input_data = std::make_pair(input, (*preprocess)(input));
        auto reranked = reranker.rerank(input_data, std::begin(candidates), std::end(candidates), *score_func);

        std::vector<ResemblaInterface::response_type> results;
        for(const auto& r: reranked){
            if(r.second < threshold || results.size() >= max_response){
                break;
            }
            results.push_back({r.first, score_func->name, r.second});
        }
        return results;
    }

protected:
    using WorkData = std::pair<string_type, typename Preprocessor::return_type>;

    const std::shared_ptr<ResemblaInterface> resembla;
    const size_t max_candidate;

    const std::shared_ptr<Preprocessor> preprocess;
    const std::shared_ptr<ScoreFunction> score_func;
    const Reranker<string_type> reranker;

    const bool preprocess_corpus;

    void loadCorpusFeatures(const std::string& corpus_path, size_t col)
    {
        std::ifstream ifs(corpus_path);
        if(ifs.fail()){
            throw std::runtime_error("input file is not available: " + corpus_path);
        }
        while(ifs.good()){
            std::string line;
            std::getline(ifs, line);
            if(ifs.eof() || line.length() == 0){
                break;
            }
            auto columns = split(line, '\t');
            if(columns.size() + 1 < col){
                continue;
            }
            corpus_features[cast_string<string_type>(columns[0])] = (*preprocess)(columns[0], columns[1]);
        }
    }

    std::unordered_map<string_type, typename Preprocessor::return_type> corpus_features;
};

}
#endif
<|endoftext|>


<commit_before>/****************************************************************
 *
 * Copyright (c) 2011
 * All rights reserved.
 *
 * Hochschule Bonn-Rhein-Sieg
 * University of Applied Sciences
 * Computer Science Department
 *
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * Author:
 * Jan Paulus, Nico Hochgeschwender, Michael Reckhaus, Azamat Shakhimardanov
 * Supervised by:
 * Gerhard K. Kraetzschmar
 *
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * This sofware is published under a dual-license: GNU Lesser General Public
 * License LGPL 2.1 and BSD license. The dual-license implies that users of this
 * code may choose which terms they prefer.
 *
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Hochschule Bonn-Rhein-Sieg nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License LGPL as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version or the BSD license.
 *
 * 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 Lesser General Public License LGPL and the BSD license for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License LGPL and BSD license along with this program.
 *
 ****************************************************************/

#ifndef _YOUBOT_SLAVE_MAILBOX_MESSAGE_H
#define	_YOUBOT_SLAVE_MAILBOX_MESSAGE_H

#include <ethercattype.h>
#include <string>
#include <time.h>

namespace youbot {

  /// Output part from the EtherCAT mailbox message of the youBot slaves

  struct mailboxOutputBuffer {
    uint8 moduleAddress; //0 = Drive  1 = Gripper
    uint8 commandNumber;
    uint8 typeNumber;
    uint8 motorNumber; //always zero
    uint32 value; //MSB first!

    mailboxOutputBuffer() : moduleAddress(0), commandNumber(0), typeNumber(0), motorNumber(0), value(0) {};
  } __attribute__((__packed__));

  /// Input part from the EtherCAT mailbox message of the youBot slaves

  struct mailboxInputBuffer {
    uint8 replyAddress;
    uint8 moduleAddress;
    uint8 status; //(e.g. 100 means “no error”)
    uint8 commandNumber;
    uint32 value; //MSB first!

    mailboxInputBuffer() : replyAddress(0), moduleAddress(0), status(0), commandNumber(0), value(0) {};
  } __attribute__((__packed__));

  ///////////////////////////////////////////////////////////////////////////////
  /// EtherCAT mailbox message of the youBot slaves
  ///////////////////////////////////////////////////////////////////////////////

 class YouBotSlaveMailboxMsg {
  public:

    mailboxOutputBuffer stctOutput;
    mailboxInputBuffer stctInput;

    // Constructor
    YouBotSlaveMailboxMsg() {
      slaveNumber = 1000;
    }

    // Constructor

    YouBotSlaveMailboxMsg(unsigned int slaveNo) {
      slaveNumber = slaveNo;
    }
    // Copy-Constructor

    YouBotSlaveMailboxMsg(const YouBotSlaveMailboxMsg& copy) {
      stctOutput = copy.stctOutput;
      stctInput = copy.stctInput;
      slaveNumber = copy.slaveNumber;
      parameterName = copy.parameterName;
    }

    // Destructor

    ~YouBotSlaveMailboxMsg() {
    }

    // assignment operator

    YouBotSlaveMailboxMsg & operator=(const YouBotSlaveMailboxMsg& copy) {
      stctOutput = copy.stctOutput;
      stctInput = copy.stctInput;
      slaveNumber = copy.slaveNumber;
      parameterName = copy.parameterName;
      return *this;
    }

    std::string parameterName;
    unsigned int slaveNumber;
  };

  ///////////////////////////////////////////////////////////////////////////////
  /// EtherCAT mailbox message of the youBot slaves (thread safe)
  ///////////////////////////////////////////////////////////////////////////////
  class YouBotSlaveMailboxMsgThreadSafe {
  public:

    DataObjectLockFree<mailboxOutputBuffer> stctOutput;
    DataObjectLockFree<mailboxInputBuffer> stctInput;

    // Constructor
    YouBotSlaveMailboxMsgThreadSafe() {
      slaveNumber.Set(1000);
    }

    // Constructor

    YouBotSlaveMailboxMsgThreadSafe(unsigned int slaveNo) {
      slaveNumber.Set(slaveNo);
    }
    // Copy-Constructor

    YouBotSlaveMailboxMsgThreadSafe(const YouBotSlaveMailboxMsgThreadSafe& copy) {
      mailboxOutputBuffer tempStctOutput;
      mailboxInputBuffer tempStctInput;
      std::string tempParameterName;
      unsigned int SlaveNumber;

      copy.stctOutput.Get(tempStctOutput);
      stctOutput.Set(tempStctOutput);

      copy.stctInput.Get(tempStctInput);
      stctInput.Set(tempStctInput);

      copy.slaveNumber.Get(SlaveNumber);
      slaveNumber.Set(SlaveNumber);

      copy.parameterName.Get(tempParameterName);
      parameterName.Set(tempParameterName);
    }

    // Destructor

    ~YouBotSlaveMailboxMsgThreadSafe() {
    }

    // assignment operator

    YouBotSlaveMailboxMsgThreadSafe & operator=(const YouBotSlaveMailboxMsgThreadSafe& copy) {
      mailboxOutputBuffer tempStctOutput;
      mailboxInputBuffer tempStctInput;
      std::string tempParameterName;
      unsigned int SlaveNumber;

      copy.stctOutput.Get(tempStctOutput);
      stctOutput.Set(tempStctOutput);

      copy.stctInput.Get(tempStctInput);
      stctInput.Set(tempStctInput);

      copy.slaveNumber.Get(SlaveNumber);
      slaveNumber.Set(SlaveNumber);

      copy.parameterName.Get(tempParameterName);
      parameterName.Set(tempParameterName);
      return *this;
    }

    DataObjectLockFree<std::string> parameterName;

    DataObjectLockFree<unsigned int> slaveNumber;
  };

} // namespace youbot

#endif	/* _YOUBOT_SLAVE_MESSAGE_H */
<commit_msg>add missing include file<commit_after>/****************************************************************
 *
 * Copyright (c) 2011
 * All rights reserved.
 *
 * Hochschule Bonn-Rhein-Sieg
 * University of Applied Sciences
 * Computer Science Department
 *
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * Author:
 * Jan Paulus, Nico Hochgeschwender, Michael Reckhaus, Azamat Shakhimardanov
 * Supervised by:
 * Gerhard K. Kraetzschmar
 *
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * This sofware is published under a dual-license: GNU Lesser General Public
 * License LGPL 2.1 and BSD license. The dual-license implies that users of this
 * code may choose which terms they prefer.
 *
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Hochschule Bonn-Rhein-Sieg nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License LGPL as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version or the BSD license.
 *
 * 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 Lesser General Public License LGPL and the BSD license for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License LGPL and BSD license along with this program.
 *
 ****************************************************************/

#ifndef _YOUBOT_SLAVE_MAILBOX_MESSAGE_H
#define	_YOUBOT_SLAVE_MAILBOX_MESSAGE_H

#include <ethercattype.h>
#include <string>
#include <time.h>
#include "generic/dataobjectlockfree/DataObjectLockFree.hpp"

namespace youbot {

  /// Output part from the EtherCAT mailbox message of the youBot slaves

  struct mailboxOutputBuffer {
    uint8 moduleAddress; //0 = Drive  1 = Gripper
    uint8 commandNumber;
    uint8 typeNumber;
    uint8 motorNumber; //always zero
    uint32 value; //MSB first!

    mailboxOutputBuffer() : moduleAddress(0), commandNumber(0), typeNumber(0), motorNumber(0), value(0) {};
  } __attribute__((__packed__));

  /// Input part from the EtherCAT mailbox message of the youBot slaves

  struct mailboxInputBuffer {
    uint8 replyAddress;
    uint8 moduleAddress;
    uint8 status; //(e.g. 100 means “no error”)
    uint8 commandNumber;
    uint32 value; //MSB first!

    mailboxInputBuffer() : replyAddress(0), moduleAddress(0), status(0), commandNumber(0), value(0) {};
  } __attribute__((__packed__));

  ///////////////////////////////////////////////////////////////////////////////
  /// EtherCAT mailbox message of the youBot slaves
  ///////////////////////////////////////////////////////////////////////////////

 class YouBotSlaveMailboxMsg {
  public:

    mailboxOutputBuffer stctOutput;
    mailboxInputBuffer stctInput;

    // Constructor
    YouBotSlaveMailboxMsg() {
      slaveNumber = 1000;
    }

    // Constructor

    YouBotSlaveMailboxMsg(unsigned int slaveNo) {
      slaveNumber = slaveNo;
    }
    // Copy-Constructor

    YouBotSlaveMailboxMsg(const YouBotSlaveMailboxMsg& copy) {
      stctOutput = copy.stctOutput;
      stctInput = copy.stctInput;
      slaveNumber = copy.slaveNumber;
      parameterName = copy.parameterName;
    }

    // Destructor

    ~YouBotSlaveMailboxMsg() {
    }

    // assignment operator

    YouBotSlaveMailboxMsg & operator=(const YouBotSlaveMailboxMsg& copy) {
      stctOutput = copy.stctOutput;
      stctInput = copy.stctInput;
      slaveNumber = copy.slaveNumber;
      parameterName = copy.parameterName;
      return *this;
    }

    std::string parameterName;
    unsigned int slaveNumber;
  };

  ///////////////////////////////////////////////////////////////////////////////
  /// EtherCAT mailbox message of the youBot slaves (thread safe)
  ///////////////////////////////////////////////////////////////////////////////
  class YouBotSlaveMailboxMsgThreadSafe {
  public:

    DataObjectLockFree<mailboxOutputBuffer> stctOutput;
    DataObjectLockFree<mailboxInputBuffer> stctInput;

    // Constructor
    YouBotSlaveMailboxMsgThreadSafe() {
      slaveNumber.Set(1000);
    }

    // Constructor

    YouBotSlaveMailboxMsgThreadSafe(unsigned int slaveNo) {
      slaveNumber.Set(slaveNo);
    }
    // Copy-Constructor

    YouBotSlaveMailboxMsgThreadSafe(const YouBotSlaveMailboxMsgThreadSafe& copy) {
      mailboxOutputBuffer tempStctOutput;
      mailboxInputBuffer tempStctInput;
      std::string tempParameterName;
      unsigned int SlaveNumber;

      copy.stctOutput.Get(tempStctOutput);
      stctOutput.Set(tempStctOutput);

      copy.stctInput.Get(tempStctInput);
      stctInput.Set(tempStctInput);

      copy.slaveNumber.Get(SlaveNumber);
      slaveNumber.Set(SlaveNumber);

      copy.parameterName.Get(tempParameterName);
      parameterName.Set(tempParameterName);
    }

    // Destructor

    ~YouBotSlaveMailboxMsgThreadSafe() {
    }

    // assignment operator

    YouBotSlaveMailboxMsgThreadSafe & operator=(const YouBotSlaveMailboxMsgThreadSafe& copy) {
      mailboxOutputBuffer tempStctOutput;
      mailboxInputBuffer tempStctInput;
      std::string tempParameterName;
      unsigned int SlaveNumber;

      copy.stctOutput.Get(tempStctOutput);
      stctOutput.Set(tempStctOutput);

      copy.stctInput.Get(tempStctInput);
      stctInput.Set(tempStctInput);

      copy.slaveNumber.Get(SlaveNumber);
      slaveNumber.Set(SlaveNumber);

      copy.parameterName.Get(tempParameterName);
      parameterName.Set(tempParameterName);
      return *this;
    }

    DataObjectLockFree<std::string> parameterName;

    DataObjectLockFree<unsigned int> slaveNumber;
  };

} // namespace youbot

#endif	/* _YOUBOT_SLAVE_MESSAGE_H */
<|endoftext|>


<commit_before>/*
  HardwareSerial.cpp - Hardware serial library for Wiring
  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.

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

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

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

  Modified 23 November 2006 by David A. Mellis
  Modified 28 September 2010 by Mark Sproul
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "wiring.h"
#include "wiring_private.h"

// this next line disables the entire HardwareSerial.cpp,
// this is so I can support Attiny series and any other chip without a uart
#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)

#include "HardwareSerial.h"

// Define constants and variables for buffering incoming serial data.  We're
// using a ring buffer (I think), in which rx_buffer_head is the index of the
// location to which to write the next incoming character and rx_buffer_tail
// is the index of the location from which to read.
#if (RAMEND < 1000)
  #define RX_BUFFER_SIZE 32
#else
  #define RX_BUFFER_SIZE 128
#endif

struct ring_buffer
{
  unsigned char buffer[RX_BUFFER_SIZE];
  int head;
  int tail;
};

#if defined(UBRRH) || defined(UBRR0H)
  ring_buffer rx_buffer  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR1H)
  ring_buffer rx_buffer1  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR2H)
  ring_buffer rx_buffer2  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR3H)
  ring_buffer rx_buffer3  =  { { 0 }, 0, 0 };
#endif

inline void store_char(unsigned char c, ring_buffer *rx_buffer)
{
  int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != rx_buffer->tail) {
    rx_buffer->buffer[rx_buffer->head] = c;
    rx_buffer->head = i;
  }
}

#if defined(USART_RX_vect)
  SIGNAL(USART_RX_vect)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8535
  #else
    #error UDR not defined
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_USART0_RECV) && defined(UDR0)
  SIGNAL(SIG_USART0_RECV)
  {
    unsigned char c  =  UDR0;
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_UART0_RECV) && defined(UDR0)
  SIGNAL(SIG_UART0_RECV)
  {
    unsigned char c  =  UDR0;
    store_char(c, &rx_buffer);
  }
//#elif defined(SIG_USART_RECV)
#elif defined(USART0_RX_vect)
  // fixed by Mark Sproul this is on the 644/644p
  //SIGNAL(SIG_USART_RECV)
  SIGNAL(USART0_RX_vect)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8, atmega32
  #else
    #error UDR not defined
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_UART_RECV)
  // this is for atmega8
  SIGNAL(SIG_UART_RECV)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;  //  atmega645
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(USBCON)
  #warning No interrupt handler for usart 0
  #warning Serial(0) is on USB interface
#else
  #error No interrupt handler for usart 0
#endif

//#if defined(SIG_USART1_RECV)
#if defined(USART1_RX_vect)
  //SIGNAL(SIG_USART1_RECV)
  SIGNAL(USART1_RX_vect)
  {
    unsigned char c = UDR1;
    store_char(c, &rx_buffer1);
  }
#elif defined(SIG_USART1_RECV)
  #error SIG_USART1_RECV
#endif

#if defined(USART2_RX_vect) && defined(UDR2)
  SIGNAL(USART2_RX_vect)
  {
    unsigned char c = UDR2;
    store_char(c, &rx_buffer2);
  }
#elif defined(SIG_USART2_RECV)
  #error SIG_USART2_RECV
#endif

#if defined(USART3_RX_vect) && defined(UDR3)
  SIGNAL(USART3_RX_vect)
  {
    unsigned char c = UDR3;
    store_char(c, &rx_buffer3);
  }
#elif defined(SIG_USART3_RECV)
  #error SIG_USART3_RECV
#endif

// Constructors ////////////////////////////////////////////////////////////////

HardwareSerial::HardwareSerial(ring_buffer *rx_buffer,
  volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
  volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
  volatile uint8_t *udr,
  uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x)
{
  _rx_buffer = rx_buffer;
  _ubrrh = ubrrh;
  _ubrrl = ubrrl;
  _ucsra = ucsra;
  _ucsrb = ucsrb;
  _udr = udr;
  _rxen = rxen;
  _txen = txen;
  _rxcie = rxcie;
  _udre = udre;
  _u2x = u2x;
}

// Public Methods //////////////////////////////////////////////////////////////

void HardwareSerial::begin(long baud)
{
  uint16_t baud_setting;
  bool use_u2x;

  // U2X mode is needed for baud rates higher than (CPU Hz / 16)
  if (baud > F_CPU / 16) {
    use_u2x = true;
  } else {
    // figure out if U2X mode would allow for a better connection

    // calculate the percent difference between the baud-rate specified and
    // the real baud rate for both U2X and non-U2X mode (0-255 error percent)
    uint8_t nonu2x_baud_error = abs((int)(255-((F_CPU/(16*(((F_CPU/8/baud-1)/2)+1))*255)/baud)));
    uint8_t u2x_baud_error = abs((int)(255-((F_CPU/(8*(((F_CPU/4/baud-1)/2)+1))*255)/baud)));

    // prefer non-U2X mode because it handles clock skew better
    use_u2x = (nonu2x_baud_error > u2x_baud_error);
  }

  if (use_u2x) {
    *_ucsra = 1 << _u2x;
    baud_setting = (F_CPU / 4 / baud - 1) / 2;
  } else {
    *_ucsra = 0;
    baud_setting = (F_CPU / 8 / baud - 1) / 2;
  }

  // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
  *_ubrrh = baud_setting >> 8;
  *_ubrrl = baud_setting;

  sbi(*_ucsrb, _rxen);
  sbi(*_ucsrb, _txen);
  sbi(*_ucsrb, _rxcie);
}

void HardwareSerial::end()
{
  cbi(*_ucsrb, _rxen);
  cbi(*_ucsrb, _txen);
  cbi(*_ucsrb, _rxcie);
}

int HardwareSerial::available(void)
{
  return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE;
}

int HardwareSerial::peek(void)
{
  if (_rx_buffer->head == _rx_buffer->tail) {
    return -1;
  } else {
    return _rx_buffer->buffer[_rx_buffer->tail];
  }
}

int HardwareSerial::read(void)
{
  // if the head isn't ahead of the tail, we don't have any characters
  if (_rx_buffer->head == _rx_buffer->tail) {
    return -1;
  } else {
    unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
    _rx_buffer->tail = (_rx_buffer->tail + 1) % RX_BUFFER_SIZE;
    return c;
  }
}

void HardwareSerial::flush()
{
  // don't reverse this or there may be problems if the RX interrupt
  // occurs after reading the value of rx_buffer_head but before writing
  // the value to rx_buffer_tail; the previous value of rx_buffer_head
  // may be written to rx_buffer_tail, making it appear as if the buffer
  // don't reverse this or there may be problems if the RX interrupt
  // occurs after reading the value of rx_buffer_head but before writing
  // the value to rx_buffer_tail; the previous value of rx_buffer_head
  // may be written to rx_buffer_tail, making it appear as if the buffer
  // were full, not empty.
  _rx_buffer->head = _rx_buffer->tail;
}

void HardwareSerial::write(uint8_t c)
{
  while (!((*_ucsra) & (1 << _udre)))
    ;

  *_udr = c;
}

// Preinstantiate Objects //////////////////////////////////////////////////////

#if defined(UBRRH) && defined(UBRRL)
  HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X);
#elif defined(UBRR0H) && defined(UBRR0L)
  HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0);
#elif defined(USBCON)
  #warning no serial port defined  (port 0)
#else
  #error no serial port defined  (port 0)
#endif

#if defined(UBRR1H)
  HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1);
#endif
#if defined(UBRR2H)
  HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2);
#endif
#if defined(UBRR3H)
  HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3);
#endif

#endif // whole file

<commit_msg>Changing baud rate calculation to always use double speed mode except for 57600 baud at 16 MHz.<commit_after>/*
  HardwareSerial.cpp - Hardware serial library for Wiring
  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.

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

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

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

  Modified 23 November 2006 by David A. Mellis
  Modified 28 September 2010 by Mark Sproul
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "wiring.h"
#include "wiring_private.h"

// this next line disables the entire HardwareSerial.cpp,
// this is so I can support Attiny series and any other chip without a uart
#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)

#include "HardwareSerial.h"

// Define constants and variables for buffering incoming serial data.  We're
// using a ring buffer (I think), in which rx_buffer_head is the index of the
// location to which to write the next incoming character and rx_buffer_tail
// is the index of the location from which to read.
#if (RAMEND < 1000)
  #define RX_BUFFER_SIZE 32
#else
  #define RX_BUFFER_SIZE 128
#endif

struct ring_buffer
{
  unsigned char buffer[RX_BUFFER_SIZE];
  int head;
  int tail;
};

#if defined(UBRRH) || defined(UBRR0H)
  ring_buffer rx_buffer  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR1H)
  ring_buffer rx_buffer1  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR2H)
  ring_buffer rx_buffer2  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR3H)
  ring_buffer rx_buffer3  =  { { 0 }, 0, 0 };
#endif

inline void store_char(unsigned char c, ring_buffer *rx_buffer)
{
  int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != rx_buffer->tail) {
    rx_buffer->buffer[rx_buffer->head] = c;
    rx_buffer->head = i;
  }
}

#if defined(USART_RX_vect)
  SIGNAL(USART_RX_vect)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8535
  #else
    #error UDR not defined
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_USART0_RECV) && defined(UDR0)
  SIGNAL(SIG_USART0_RECV)
  {
    unsigned char c  =  UDR0;
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_UART0_RECV) && defined(UDR0)
  SIGNAL(SIG_UART0_RECV)
  {
    unsigned char c  =  UDR0;
    store_char(c, &rx_buffer);
  }
//#elif defined(SIG_USART_RECV)
#elif defined(USART0_RX_vect)
  // fixed by Mark Sproul this is on the 644/644p
  //SIGNAL(SIG_USART_RECV)
  SIGNAL(USART0_RX_vect)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8, atmega32
  #else
    #error UDR not defined
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_UART_RECV)
  // this is for atmega8
  SIGNAL(SIG_UART_RECV)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;  //  atmega645
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(USBCON)
  #warning No interrupt handler for usart 0
  #warning Serial(0) is on USB interface
#else
  #error No interrupt handler for usart 0
#endif

//#if defined(SIG_USART1_RECV)
#if defined(USART1_RX_vect)
  //SIGNAL(SIG_USART1_RECV)
  SIGNAL(USART1_RX_vect)
  {
    unsigned char c = UDR1;
    store_char(c, &rx_buffer1);
  }
#elif defined(SIG_USART1_RECV)
  #error SIG_USART1_RECV
#endif

#if defined(USART2_RX_vect) && defined(UDR2)
  SIGNAL(USART2_RX_vect)
  {
    unsigned char c = UDR2;
    store_char(c, &rx_buffer2);
  }
#elif defined(SIG_USART2_RECV)
  #error SIG_USART2_RECV
#endif

#if defined(USART3_RX_vect) && defined(UDR3)
  SIGNAL(USART3_RX_vect)
  {
    unsigned char c = UDR3;
    store_char(c, &rx_buffer3);
  }
#elif defined(SIG_USART3_RECV)
  #error SIG_USART3_RECV
#endif

// Constructors ////////////////////////////////////////////////////////////////

HardwareSerial::HardwareSerial(ring_buffer *rx_buffer,
  volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
  volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
  volatile uint8_t *udr,
  uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x)
{
  _rx_buffer = rx_buffer;
  _ubrrh = ubrrh;
  _ubrrl = ubrrl;
  _ucsra = ucsra;
  _ucsrb = ucsrb;
  _udr = udr;
  _rxen = rxen;
  _txen = txen;
  _rxcie = rxcie;
  _udre = udre;
  _u2x = u2x;
}

// Public Methods //////////////////////////////////////////////////////////////

void HardwareSerial::begin(long baud)
{
  uint16_t baud_setting;
  bool use_u2x = true;

#if F_CPU == 16000000UL
  // hardcoded exception for compatibility with the bootloader shipped
  // with the Duemilanove and previous boards and the firmware on the 8U2
  // on the Uno and Mega 2560.
  if (baud == 57600) {
    use_u2x = false;
  }
#endif

  if (use_u2x) {
    *_ucsra = 1 << _u2x;
    baud_setting = (F_CPU / 4 / baud - 1) / 2;
  } else {
    *_ucsra = 0;
    baud_setting = (F_CPU / 8 / baud - 1) / 2;
  }

  // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
  *_ubrrh = baud_setting >> 8;
  *_ubrrl = baud_setting;

  sbi(*_ucsrb, _rxen);
  sbi(*_ucsrb, _txen);
  sbi(*_ucsrb, _rxcie);
}

void HardwareSerial::end()
{
  cbi(*_ucsrb, _rxen);
  cbi(*_ucsrb, _txen);
  cbi(*_ucsrb, _rxcie);
}

int HardwareSerial::available(void)
{
  return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE;
}

int HardwareSerial::peek(void)
{
  if (_rx_buffer->head == _rx_buffer->tail) {
    return -1;
  } else {
    return _rx_buffer->buffer[_rx_buffer->tail];
  }
}

int HardwareSerial::read(void)
{
  // if the head isn't ahead of the tail, we don't have any characters
  if (_rx_buffer->head == _rx_buffer->tail) {
    return -1;
  } else {
    unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
    _rx_buffer->tail = (_rx_buffer->tail + 1) % RX_BUFFER_SIZE;
    return c;
  }
}

void HardwareSerial::flush()
{
  // don't reverse this or there may be problems if the RX interrupt
  // occurs after reading the value of rx_buffer_head but before writing
  // the value to rx_buffer_tail; the previous value of rx_buffer_head
  // may be written to rx_buffer_tail, making it appear as if the buffer
  // don't reverse this or there may be problems if the RX interrupt
  // occurs after reading the value of rx_buffer_head but before writing
  // the value to rx_buffer_tail; the previous value of rx_buffer_head
  // may be written to rx_buffer_tail, making it appear as if the buffer
  // were full, not empty.
  _rx_buffer->head = _rx_buffer->tail;
}

void HardwareSerial::write(uint8_t c)
{
  while (!((*_ucsra) & (1 << _udre)))
    ;

  *_udr = c;
}

// Preinstantiate Objects //////////////////////////////////////////////////////

#if defined(UBRRH) && defined(UBRRL)
  HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X);
#elif defined(UBRR0H) && defined(UBRR0L)
  HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0);
#elif defined(USBCON)
  #warning no serial port defined  (port 0)
#else
  #error no serial port defined  (port 0)
#endif

#if defined(UBRR1H)
  HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1);
#endif
#if defined(UBRR2H)
  HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2);
#endif
#if defined(UBRR3H)
  HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3);
#endif

#endif // whole file

<|endoftext|>


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

#include <cassert>
#include <cstdint>
#include <limits>

#include "joynr/Settings.h"
#include "joynr/Util.h"
#include "joynr/system/RoutingTypes/UdsAddress.h"
#include "joynr/system/RoutingTypes/UdsClientAddress.h"

namespace joynr
{

const std::string& UdsSettings::DEFAULT_UDS_SETTINGS_FILENAME()
{
    static const std::string value("default-uds.settings");
    return value;
}

UdsSettings::UdsSettings(Settings& settings) : _settings(settings)
{
    _settings.fillEmptySettingsWithDefaults(DEFAULT_UDS_SETTINGS_FILENAME());
    checkSettings();
}

void UdsSettings::checkSettings()
{
    if (!_settings.contains(SETTING_SOCKET_PATH())) {
        setSocketPath(DEFAULT_SOCKET_PATH());
    }

    if (!_settings.contains(SETTING_CONNECT_SLEEP_TIME_MS())) {
        setConnectSleepTimeMs(DEFAULT_CONNECT_SLEEP_TIME_MS());
    }

    if (!_settings.contains(SETTING_CLIENT_ID())) {
        setClientId(joynr::util::createUuid());
    }

    if (!_settings.contains(SETTING_SENDING_QUEUE_SIZE())) {
        setSendingQueueSize(DEFAULT_SENDING_QUEUE_SIZE());
    }

    if (!_settings.contains(SETTING_READ_WRITE_TIMEOUT())) {
        setReadWriteTimeout(DEFAULT_READ_WRITE_TIMEOUT());
    }
}

const std::string& UdsSettings::SETTING_SOCKET_PATH()
{
    static const std::string value("uds/socket-path");
    return value;
}

const std::string& UdsSettings::SETTING_CONNECT_SLEEP_TIME_MS()
{
    static const std::string value("uds/connect-sleep-time-ms");
    return value;
}

const std::string& UdsSettings::SETTING_CLIENT_ID()
{
    static const std::string value("uds/client-id");
    return value;
}

std::string UdsSettings::getSocketPath() const
{
    return _settings.get<std::string>(UdsSettings::SETTING_SOCKET_PATH());
}

void UdsSettings::setSocketPath(const std::string& socketPath)
{
    _settings.set(UdsSettings::SETTING_SOCKET_PATH(), socketPath);
}

std::chrono::milliseconds UdsSettings::getConnectSleepTimeMs() const
{
    return std::chrono::milliseconds(
            _settings.get<std::int64_t>(UdsSettings::SETTING_CONNECT_SLEEP_TIME_MS()));
}

void UdsSettings::setConnectSleepTimeMs(const std::chrono::milliseconds connectSleepTimeMs)
{
    _settings.set(UdsSettings::SETTING_CONNECT_SLEEP_TIME_MS(), connectSleepTimeMs.count());
}

std::string UdsSettings::getClientId() const
{
    return _settings.get<std::string>(UdsSettings::SETTING_CLIENT_ID());
}

void UdsSettings::setClientId(const std::string& clientId)
{
    _settings.set(UdsSettings::SETTING_CLIENT_ID(), clientId);
}

const std::string& UdsSettings::DEFAULT_SOCKET_PATH()
{
    static const std::string value("/var/run/joynr/cluster-controller.sock");
    return value;
}

std::chrono::milliseconds UdsSettings::DEFAULT_CONNECT_SLEEP_TIME_MS()
{
    static const std::chrono::milliseconds value(500);
    return value;
}

const std::string& UdsSettings::SETTING_SENDING_QUEUE_SIZE()
{
    static const std::string value("uds/sending-queue-size");
    return value;
}

const std::size_t& UdsSettings::DEFAULT_SENDING_QUEUE_SIZE()
{
    static const std::size_t value{1024};
    return value;
}
std::size_t UdsSettings::getSendingQueueSize() const
{
    const auto sendingQueueSizeStr =
            _settings.get<std::string>(UdsSettings::SETTING_SENDING_QUEUE_SIZE());
    try {
        const auto sendingQueueSize = std::stoul(sendingQueueSizeStr);
        return sendingQueueSize; // In case of zero, an additional message will trigger a reschedule
                                 // if one message is still processed.
    } catch (const std::logic_error& ex) {
        JOYNR_LOG_ERROR(logger(),
                        "Cannot parse ",
                        UdsSettings::SETTING_SENDING_QUEUE_SIZE(),
                        " value '",
                        sendingQueueSizeStr,
                        " '. Exception: ",
                        ex.what());
    }
    return DEFAULT_SENDING_QUEUE_SIZE();
}

void UdsSettings::setSendingQueueSize(const std::size_t& queueSize)
{
    _settings.set(UdsSettings::SETTING_SENDING_QUEUE_SIZE(), std::to_string(queueSize));
}

const std::string& UdsSettings::SETTING_READ_WRITE_TIMEOUT()
{
    static const std::string value("uds/read-write-timeout");
    return value;
}

std::chrono::milliseconds UdsSettings::DEFAULT_READ_WRITE_TIMEOUT()
{
    static const std::chrono::milliseconds value(1000);
    return value;
}

std::chrono::milliseconds UdsSettings::getReadWriteTimeout() const
{
    return std::chrono::milliseconds(
            _settings.get<std::int64_t>(UdsSettings::SETTING_READ_WRITE_TIMEOUT()));
}

void UdsSettings::setReadWriteTimeout(const std::chrono::milliseconds timeout)
{
    _settings.set(UdsSettings::SETTING_READ_WRITE_TIMEOUT(), timeout.count());
}

joynr::system::RoutingTypes::UdsAddress UdsSettings::createClusterControllerMessagingAddress() const
{
    return system::RoutingTypes::UdsAddress(getSocketPath());
}

system::RoutingTypes::UdsClientAddress UdsSettings::createClientMessagingAddress() const
{
    return system::RoutingTypes::UdsClientAddress(getClientId());
}

bool UdsSettings::contains(const std::string& key) const
{
    return _settings.contains(key);
}

void UdsSettings::printSettings() const
{
    JOYNR_LOG_INFO(logger(),
                   "SETTING: {} = {}",
                   SETTING_SOCKET_PATH(),
                   _settings.get<std::string>(SETTING_SOCKET_PATH()));

    JOYNR_LOG_INFO(logger(),
                   "SETTING: {} = {}",
                   SETTING_CONNECT_SLEEP_TIME_MS(),
                   _settings.get<std::string>(SETTING_CONNECT_SLEEP_TIME_MS()));

    JOYNR_LOG_INFO(logger(),
                   "SETTING: {} = {}",
                   SETTING_CLIENT_ID(),
                   _settings.get<std::string>(SETTING_CLIENT_ID()));

    JOYNR_LOG_INFO(logger(),
                   "SETTING: {} = {}",
                   SETTING_SENDING_QUEUE_SIZE(),
                   _settings.get<std::string>(SETTING_SENDING_QUEUE_SIZE()));
}

} // namespace joynr
<commit_msg>[C++] Print SETTING_READ_WRITE_TIMEOUT in UdsSettings::PrintSettings<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2020 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include "joynr/UdsSettings.h"

#include <cassert>
#include <cstdint>
#include <limits>

#include "joynr/Settings.h"
#include "joynr/Util.h"
#include "joynr/system/RoutingTypes/UdsAddress.h"
#include "joynr/system/RoutingTypes/UdsClientAddress.h"

namespace joynr
{

const std::string& UdsSettings::DEFAULT_UDS_SETTINGS_FILENAME()
{
    static const std::string value("default-uds.settings");
    return value;
}

UdsSettings::UdsSettings(Settings& settings) : _settings(settings)
{
    _settings.fillEmptySettingsWithDefaults(DEFAULT_UDS_SETTINGS_FILENAME());
    checkSettings();
}

void UdsSettings::checkSettings()
{
    if (!_settings.contains(SETTING_SOCKET_PATH())) {
        setSocketPath(DEFAULT_SOCKET_PATH());
    }

    if (!_settings.contains(SETTING_CONNECT_SLEEP_TIME_MS())) {
        setConnectSleepTimeMs(DEFAULT_CONNECT_SLEEP_TIME_MS());
    }

    if (!_settings.contains(SETTING_CLIENT_ID())) {
        setClientId(joynr::util::createUuid());
    }

    if (!_settings.contains(SETTING_SENDING_QUEUE_SIZE())) {
        setSendingQueueSize(DEFAULT_SENDING_QUEUE_SIZE());
    }

    if (!_settings.contains(SETTING_READ_WRITE_TIMEOUT())) {
        setReadWriteTimeout(DEFAULT_READ_WRITE_TIMEOUT());
    }
}

const std::string& UdsSettings::SETTING_SOCKET_PATH()
{
    static const std::string value("uds/socket-path");
    return value;
}

const std::string& UdsSettings::SETTING_CONNECT_SLEEP_TIME_MS()
{
    static const std::string value("uds/connect-sleep-time-ms");
    return value;
}

const std::string& UdsSettings::SETTING_CLIENT_ID()
{
    static const std::string value("uds/client-id");
    return value;
}

std::string UdsSettings::getSocketPath() const
{
    return _settings.get<std::string>(UdsSettings::SETTING_SOCKET_PATH());
}

void UdsSettings::setSocketPath(const std::string& socketPath)
{
    _settings.set(UdsSettings::SETTING_SOCKET_PATH(), socketPath);
}

std::chrono::milliseconds UdsSettings::getConnectSleepTimeMs() const
{
    return std::chrono::milliseconds(
            _settings.get<std::int64_t>(UdsSettings::SETTING_CONNECT_SLEEP_TIME_MS()));
}

void UdsSettings::setConnectSleepTimeMs(const std::chrono::milliseconds connectSleepTimeMs)
{
    _settings.set(UdsSettings::SETTING_CONNECT_SLEEP_TIME_MS(), connectSleepTimeMs.count());
}

std::string UdsSettings::getClientId() const
{
    return _settings.get<std::string>(UdsSettings::SETTING_CLIENT_ID());
}

void UdsSettings::setClientId(const std::string& clientId)
{
    _settings.set(UdsSettings::SETTING_CLIENT_ID(), clientId);
}

const std::string& UdsSettings::DEFAULT_SOCKET_PATH()
{
    static const std::string value("/var/run/joynr/cluster-controller.sock");
    return value;
}

std::chrono::milliseconds UdsSettings::DEFAULT_CONNECT_SLEEP_TIME_MS()
{
    static const std::chrono::milliseconds value(500);
    return value;
}

const std::string& UdsSettings::SETTING_SENDING_QUEUE_SIZE()
{
    static const std::string value("uds/sending-queue-size");
    return value;
}

const std::size_t& UdsSettings::DEFAULT_SENDING_QUEUE_SIZE()
{
    static const std::size_t value{1024};
    return value;
}
std::size_t UdsSettings::getSendingQueueSize() const
{
    const auto sendingQueueSizeStr =
            _settings.get<std::string>(UdsSettings::SETTING_SENDING_QUEUE_SIZE());
    try {
        const auto sendingQueueSize = std::stoul(sendingQueueSizeStr);
        return sendingQueueSize; // In case of zero, an additional message will trigger a reschedule
                                 // if one message is still processed.
    } catch (const std::logic_error& ex) {
        JOYNR_LOG_ERROR(logger(),
                        "Cannot parse ",
                        UdsSettings::SETTING_SENDING_QUEUE_SIZE(),
                        " value '",
                        sendingQueueSizeStr,
                        " '. Exception: ",
                        ex.what());
    }
    return DEFAULT_SENDING_QUEUE_SIZE();
}

void UdsSettings::setSendingQueueSize(const std::size_t& queueSize)
{
    _settings.set(UdsSettings::SETTING_SENDING_QUEUE_SIZE(), std::to_string(queueSize));
}

const std::string& UdsSettings::SETTING_READ_WRITE_TIMEOUT()
{
    static const std::string value("uds/read-write-timeout");
    return value;
}

std::chrono::milliseconds UdsSettings::DEFAULT_READ_WRITE_TIMEOUT()
{
    static const std::chrono::milliseconds value(1000);
    return value;
}

std::chrono::milliseconds UdsSettings::getReadWriteTimeout() const
{
    return std::chrono::milliseconds(
            _settings.get<std::int64_t>(UdsSettings::SETTING_READ_WRITE_TIMEOUT()));
}

void UdsSettings::setReadWriteTimeout(const std::chrono::milliseconds timeout)
{
    _settings.set(UdsSettings::SETTING_READ_WRITE_TIMEOUT(), timeout.count());
}

joynr::system::RoutingTypes::UdsAddress UdsSettings::createClusterControllerMessagingAddress() const
{
    return system::RoutingTypes::UdsAddress(getSocketPath());
}

system::RoutingTypes::UdsClientAddress UdsSettings::createClientMessagingAddress() const
{
    return system::RoutingTypes::UdsClientAddress(getClientId());
}

bool UdsSettings::contains(const std::string& key) const
{
    return _settings.contains(key);
}

void UdsSettings::printSettings() const
{
    JOYNR_LOG_INFO(logger(),
                   "SETTING: {} = {}",
                   SETTING_SOCKET_PATH(),
                   _settings.get<std::string>(SETTING_SOCKET_PATH()));

    JOYNR_LOG_INFO(logger(),
                   "SETTING: {} = {}",
                   SETTING_CONNECT_SLEEP_TIME_MS(),
                   _settings.get<std::string>(SETTING_CONNECT_SLEEP_TIME_MS()));

    JOYNR_LOG_INFO(logger(),
                   "SETTING: {} = {}",
                   SETTING_CLIENT_ID(),
                   _settings.get<std::string>(SETTING_CLIENT_ID()));

    JOYNR_LOG_INFO(logger(),
                   "SETTING: {} = {}",
                   SETTING_SENDING_QUEUE_SIZE(),
                   _settings.get<std::string>(SETTING_SENDING_QUEUE_SIZE()));

    JOYNR_LOG_INFO(logger(),
                   "SETTING: {} = {}",
                   SETTING_READ_WRITE_TIMEOUT(),
                   _settings.get<std::string>(SETTING_READ_WRITE_TIMEOUT()));
}

} // namespace joynr
<|endoftext|>


<commit_before>#include <sys/time.h>
#include <sys/syscall.h>
#include <stdarg.h>
#include <string.h>

#include "log.h"
#include "config.h"
#include "simulator.h"
#include "core_manager.h"

using namespace std;

Log *Log::_singleton;

const UInt32 Log::MODULE_LENGTH;

static string formatFileName(const char* s)
{
   return Sim()->getConfig()->formatOutputFileName(s);
}

Log::Log(Config &config)
   : _coreCount(config.getTotalCores())
   , _startTime(0)
{
   assert(Config::getSingleton()->getProcessCount() != 0);

   _coreFiles = new FILE* [_coreCount];
   _simFiles = new FILE* [_coreCount];

   for (core_id_t i = 0; i < _coreCount; i++)
   {
      _coreFiles[i] = NULL;
      _simFiles[i] = NULL;
   }

   _coreLocks = new Lock [_coreCount];
   _simLocks = new Lock [_coreCount];

   _systemFile = NULL;

   _defaultFile = fopen(formatFileName("system-default.log").c_str(),"w");

   std::set<std::string> disabledModulesUnformatted;
   Config::getSingleton()->getDisabledLogModules(disabledModulesUnformatted);
   for (std::set<std::string>::iterator it = disabledModulesUnformatted.begin();
        it != disabledModulesUnformatted.end();
        it++)
   {
      string formatted;

      for (unsigned int i = 0; i < min(MODULE_LENGTH, it->length()); i++)
      {
         formatted.push_back((*it)[i]);
      }

      for (unsigned int i = formatted.length(); i < MODULE_LENGTH; i++)
      {
         formatted.push_back(' ');
      }

      assert(formatted.length() == MODULE_LENGTH);
      _disabledModules.insert(formatted);
   }

   _loggingEnabled = Config::getSingleton()->getLoggingEnabled();

   assert(_singleton == NULL);
   _singleton = this;
}

Log::~Log()
{
   _singleton = NULL;

   for (core_id_t i = 0; i < _coreCount; i++)
   {
      if (_coreFiles[i])
         fclose(_coreFiles[i]);
      if (_simFiles[i])
         fclose(_simFiles[i]);
   }

   delete [] _coreLocks;
   delete [] _simLocks;
   delete [] _coreFiles;
   delete [] _simFiles;

   if (_systemFile)
      fclose(_systemFile);
   fclose(_defaultFile);
}

Log* Log::getSingleton()
{
   assert(_singleton);
   return _singleton;
}

Boolean Log::isEnabled(const char* module)
{
   return _disabledModules.find(module) == _disabledModules.end();
}

Boolean Log::isLoggingEnabled()
{
   return _loggingEnabled;
}

UInt64 Log::getTimestamp()
{
   timeval t;
   gettimeofday(&t, NULL);
   UInt64 time = (((UInt64)t.tv_sec) * 1000000 + t.tv_usec);
   if (_startTime == 0) _startTime = time;
   return time - _startTime;
}

void Log::discoverCore(core_id_t *core_id, bool *sim_thread)
{
   CoreManager *core_manager;

   if (!Sim() || !(core_manager = Sim()->getCoreManager()))
   {
      *core_id = INVALID_CORE_ID;
      *sim_thread = false;
      return;
   }

   *core_id = core_manager->getCurrentCoreID();
   if (*core_id != INVALID_CORE_ID)
   {
      *sim_thread = false;
      return;
   }
   else
   {
      *core_id = core_manager->getCurrentSimThreadCoreID();
      *sim_thread = true;
      return;
   }
}

void Log::getFile(core_id_t core_id, bool sim_thread, FILE **file, Lock **lock)
{
   // we use on-demand file allocation to prevent contention between
   // processes for files

   *file = NULL;
   *lock = NULL;

   if (core_id == INVALID_CORE_ID)
   {
      // System file -- use process num if available
      UInt32 procNum = Config::getSingleton()->getCurrentProcessNum();

      if (procNum != (UInt32)-1)
      {
         if (_systemFile == NULL)
         {
            assert(procNum < Config::getSingleton()->getProcessCount());
            char filename[256];
            sprintf(filename, "system_%u.log", procNum);
            _systemFile = fopen(formatFileName(filename).c_str(), "w");
            assert(_systemFile != NULL);
         }

         *file = _systemFile;
         *lock = &_systemLock;
      }
      else
      {
         *file = _defaultFile;
         *lock = &_defaultLock;
      }
   }
   else if (sim_thread)
   {
      // sim thread file
      if (_simFiles[core_id] == NULL)
      {
         assert(core_id < _coreCount);
         char filename[256];
         sprintf(filename, "sim_%u.log", core_id);
         _simFiles[core_id] = fopen(formatFileName(filename).c_str(), "w");
         assert(_simFiles[core_id] != NULL);
      }

      *file = _simFiles[core_id];
      *lock = &_simLocks[core_id];
   }
   else
   {
      // core file
      if (_coreFiles[core_id] == NULL)
      {
         assert(core_id < _coreCount);
         char filename[256];
         sprintf(filename, "app_%u.log", core_id);
         _coreFiles[core_id] = fopen(formatFileName(filename).c_str(), "w");
         assert(_coreFiles[core_id] != NULL);
      }

      // Core file
      *file = _coreFiles[core_id];
      *lock = &_coreLocks[core_id];
   }
}

std::string Log::getModule(const char *filename)
{
#ifdef LOCK_LOGS
   ScopedLock sl(_modules_lock);
#endif
   std::map<const char*, std::string>::const_iterator it = _modules.find(filename);

   if (it != _modules.end())
   {
      return it->second;
   }
   else
   {
      // build module string
      string mod;

      // find actual file name ...
      const char *ptr = strrchr(filename, '/');
      if (ptr != NULL)
         filename = ptr + 1;

      for (UInt32 i = 0; i < MODULE_LENGTH && filename[i] != '\0'; i++)
         mod.push_back(filename[i]);

      while (mod.length() < MODULE_LENGTH)
         mod.push_back(' ');

      pair<const char*, std::string> p(filename, mod);
      _modules.insert(p);

      return mod;
   }
}

void Log::log(ErrorState err, const char* source_file, SInt32 source_line, const char *format, ...)
{
   if (!_loggingEnabled && err != Error)
      return;

   // Called in LOG_PRINT macro (see log.h)
//   if (!isEnabled(source_file))
//      return;

   core_id_t core_id;
   bool sim_thread;
   discoverCore(&core_id, &sim_thread);

   FILE *file;
   Lock *lock;

   getFile(core_id, sim_thread, &file, &lock);
   int tid = syscall(__NR_gettid);

   char message[512];
   char *p = message;

   // This is ugly, but it just prints the time stamp, process number, core number, source file/line
   if (core_id != INVALID_CORE_ID) // valid core id
      p += sprintf(p, "%-10llu [%5d]  (%2i) [%2i]%s[%s:%4d]  ", getTimestamp(), tid, Config::getSingleton()->getCurrentProcessNum(), core_id, (sim_thread ? "* " : "  "), source_file, source_line);
   else if (Config::getSingleton()->getCurrentProcessNum() != (UInt32)-1) // valid proc id
      p += sprintf(p, "%-10llu [%5d]  (%2i) [  ]  [%s:%4d]  ", getTimestamp(), tid, Config::getSingleton()->getCurrentProcessNum(), source_file, source_line);
   else // who knows
      p += sprintf(p, "%-10llu [%5d]  (  ) [  ]  [%s:%4d]  ", getTimestamp(), tid, source_file, source_line);

   switch (err)
   {
   case None:
   default:
      break;

   case Warning:
      p += sprintf(p, "*WARNING* ");
      break;

   case Error:
      p += sprintf(p, "*ERROR* ");
      break;
   };

   va_list args;
   va_start(args, format);
   p += vsprintf(p, format, args);
   va_end(args);

   p += sprintf(p, "\n");

   lock->acquire();

   fputs(message, file);
   fflush(file);

   lock->release();

   switch (err)
   {
   case Error:
      fputs(message, stderr);
      abort();
      break;

   case Warning:
      fputs(message, stderr);
      break;

   case None:
   default:
      break;
   }
}
<commit_msg>[log] Print out warnings even if logging is disabled.<commit_after>#include <sys/time.h>
#include <sys/syscall.h>
#include <stdarg.h>
#include <string.h>

#include "log.h"
#include "config.h"
#include "simulator.h"
#include "core_manager.h"

using namespace std;

Log *Log::_singleton;

const UInt32 Log::MODULE_LENGTH;

static string formatFileName(const char* s)
{
   return Sim()->getConfig()->formatOutputFileName(s);
}

Log::Log(Config &config)
   : _coreCount(config.getTotalCores())
   , _startTime(0)
{
   assert(Config::getSingleton()->getProcessCount() != 0);

   _coreFiles = new FILE* [_coreCount];
   _simFiles = new FILE* [_coreCount];

   for (core_id_t i = 0; i < _coreCount; i++)
   {
      _coreFiles[i] = NULL;
      _simFiles[i] = NULL;
   }

   _coreLocks = new Lock [_coreCount];
   _simLocks = new Lock [_coreCount];

   _systemFile = NULL;

   _defaultFile = fopen(formatFileName("system-default.log").c_str(),"w");

   std::set<std::string> disabledModulesUnformatted;
   Config::getSingleton()->getDisabledLogModules(disabledModulesUnformatted);
   for (std::set<std::string>::iterator it = disabledModulesUnformatted.begin();
        it != disabledModulesUnformatted.end();
        it++)
   {
      string formatted;

      for (unsigned int i = 0; i < min(MODULE_LENGTH, it->length()); i++)
      {
         formatted.push_back((*it)[i]);
      }

      for (unsigned int i = formatted.length(); i < MODULE_LENGTH; i++)
      {
         formatted.push_back(' ');
      }

      assert(formatted.length() == MODULE_LENGTH);
      _disabledModules.insert(formatted);
   }

   _loggingEnabled = Config::getSingleton()->getLoggingEnabled();

   assert(_singleton == NULL);
   _singleton = this;
}

Log::~Log()
{
   _singleton = NULL;

   for (core_id_t i = 0; i < _coreCount; i++)
   {
      if (_coreFiles[i])
         fclose(_coreFiles[i]);
      if (_simFiles[i])
         fclose(_simFiles[i]);
   }

   delete [] _coreLocks;
   delete [] _simLocks;
   delete [] _coreFiles;
   delete [] _simFiles;

   if (_systemFile)
      fclose(_systemFile);
   fclose(_defaultFile);
}

Log* Log::getSingleton()
{
   assert(_singleton);
   return _singleton;
}

Boolean Log::isEnabled(const char* module)
{
   return _disabledModules.find(module) == _disabledModules.end();
}

Boolean Log::isLoggingEnabled()
{
   return _loggingEnabled;
}

UInt64 Log::getTimestamp()
{
   timeval t;
   gettimeofday(&t, NULL);
   UInt64 time = (((UInt64)t.tv_sec) * 1000000 + t.tv_usec);
   if (_startTime == 0) _startTime = time;
   return time - _startTime;
}

void Log::discoverCore(core_id_t *core_id, bool *sim_thread)
{
   CoreManager *core_manager;

   if (!Sim() || !(core_manager = Sim()->getCoreManager()))
   {
      *core_id = INVALID_CORE_ID;
      *sim_thread = false;
      return;
   }

   *core_id = core_manager->getCurrentCoreID();
   if (*core_id != INVALID_CORE_ID)
   {
      *sim_thread = false;
      return;
   }
   else
   {
      *core_id = core_manager->getCurrentSimThreadCoreID();
      *sim_thread = true;
      return;
   }
}

void Log::getFile(core_id_t core_id, bool sim_thread, FILE **file, Lock **lock)
{
   // we use on-demand file allocation to prevent contention between
   // processes for files

   *file = NULL;
   *lock = NULL;

   if (core_id == INVALID_CORE_ID)
   {
      // System file -- use process num if available
      UInt32 procNum = Config::getSingleton()->getCurrentProcessNum();

      if (procNum != (UInt32)-1)
      {
         if (_systemFile == NULL)
         {
            assert(procNum < Config::getSingleton()->getProcessCount());
            char filename[256];
            sprintf(filename, "system_%u.log", procNum);
            _systemFile = fopen(formatFileName(filename).c_str(), "w");
            assert(_systemFile != NULL);
         }

         *file = _systemFile;
         *lock = &_systemLock;
      }
      else
      {
         *file = _defaultFile;
         *lock = &_defaultLock;
      }
   }
   else if (sim_thread)
   {
      // sim thread file
      if (_simFiles[core_id] == NULL)
      {
         assert(core_id < _coreCount);
         char filename[256];
         sprintf(filename, "sim_%u.log", core_id);
         _simFiles[core_id] = fopen(formatFileName(filename).c_str(), "w");
         assert(_simFiles[core_id] != NULL);
      }

      *file = _simFiles[core_id];
      *lock = &_simLocks[core_id];
   }
   else
   {
      // core file
      if (_coreFiles[core_id] == NULL)
      {
         assert(core_id < _coreCount);
         char filename[256];
         sprintf(filename, "app_%u.log", core_id);
         _coreFiles[core_id] = fopen(formatFileName(filename).c_str(), "w");
         assert(_coreFiles[core_id] != NULL);
      }

      // Core file
      *file = _coreFiles[core_id];
      *lock = &_coreLocks[core_id];
   }
}

std::string Log::getModule(const char *filename)
{
#ifdef LOCK_LOGS
   ScopedLock sl(_modules_lock);
#endif
   std::map<const char*, std::string>::const_iterator it = _modules.find(filename);

   if (it != _modules.end())
   {
      return it->second;
   }
   else
   {
      // build module string
      string mod;

      // find actual file name ...
      const char *ptr = strrchr(filename, '/');
      if (ptr != NULL)
         filename = ptr + 1;

      for (UInt32 i = 0; i < MODULE_LENGTH && filename[i] != '\0'; i++)
         mod.push_back(filename[i]);

      while (mod.length() < MODULE_LENGTH)
         mod.push_back(' ');

      pair<const char*, std::string> p(filename, mod);
      _modules.insert(p);

      return mod;
   }
}

void Log::log(ErrorState err, const char* source_file, SInt32 source_line, const char *format, ...)
{
   if (!_loggingEnabled && err == None)
      return;

   // Called in LOG_PRINT macro (see log.h)
//   if (!isEnabled(source_file))
//      return;

   core_id_t core_id;
   bool sim_thread;
   discoverCore(&core_id, &sim_thread);

   FILE *file;
   Lock *lock;

   getFile(core_id, sim_thread, &file, &lock);
   int tid = syscall(__NR_gettid);

   char message[512];
   char *p = message;

   // This is ugly, but it just prints the time stamp, process number, core number, source file/line
   if (core_id != INVALID_CORE_ID) // valid core id
      p += sprintf(p, "%-10llu [%5d]  (%2i) [%2i]%s[%s:%4d]  ", getTimestamp(), tid, Config::getSingleton()->getCurrentProcessNum(), core_id, (sim_thread ? "* " : "  "), source_file, source_line);
   else if (Config::getSingleton()->getCurrentProcessNum() != (UInt32)-1) // valid proc id
      p += sprintf(p, "%-10llu [%5d]  (%2i) [  ]  [%s:%4d]  ", getTimestamp(), tid, Config::getSingleton()->getCurrentProcessNum(), source_file, source_line);
   else // who knows
      p += sprintf(p, "%-10llu [%5d]  (  ) [  ]  [%s:%4d]  ", getTimestamp(), tid, source_file, source_line);

   switch (err)
   {
   case None:
   default:
      break;

   case Warning:
      p += sprintf(p, "*WARNING* ");
      break;

   case Error:
      p += sprintf(p, "*ERROR* ");
      break;
   };

   va_list args;
   va_start(args, format);
   p += vsprintf(p, format, args);
   va_end(args);

   p += sprintf(p, "\n");

   lock->acquire();

   fputs(message, file);
   fflush(file);

   lock->release();

   switch (err)
   {
   case Error:
      fputs(message, stderr);
      abort();
      break;

   case Warning:
      fputs(message, stderr);
      break;

   case None:
   default:
      break;
   }
}
<|endoftext|>