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

#include "base/logging.h"
#include "media/base/callback.h"
#include "media/base/media.h"
#include "remoting/base/capture_data.h"
#include "remoting/base/encoder_vp8.h"
#include "remoting/proto/video.pb.h"

extern "C" {
#define VPX_CODEC_DISABLE_COMPAT 1
#include "third_party/libvpx/include/vpx/vpx_codec.h"
#include "third_party/libvpx/include/vpx/vpx_encoder.h"
#include "third_party/libvpx/include/vpx/vp8cx.h"
}

namespace remoting {

EncoderVp8::EncoderVp8()
    : initialized_(false),
      codec_(NULL),
      image_(NULL),
      last_timestamp_(0) {
}

EncoderVp8::~EncoderVp8() {
  if (initialized_) {
    vpx_codec_err_t ret = vpx_codec_destroy(codec_.get());
    DCHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec";
  }
}

bool EncoderVp8::Init(int width, int height) {
  codec_.reset(new vpx_codec_ctx_t());
  image_.reset(new vpx_image_t());
  memset(image_.get(), 0, sizeof(vpx_image_t));

  image_->fmt = VPX_IMG_FMT_YV12;

  // libvpx seems to require both to be assigned.
  image_->d_w = width;
  image_->w = width;
  image_->d_h = height;
  image_->h = height;

  vpx_codec_enc_cfg_t config;
  const vpx_codec_iface_t* algo =
      (const vpx_codec_iface_t*)media::GetVp8CxAlgoAddress();
  CHECK(algo);
  vpx_codec_err_t ret = vpx_codec_enc_config_default(algo, &config, 0);
  if (ret != VPX_CODEC_OK)
    return false;

  // TODO(hclam): Tune the parameters to better suit the application.
  config.rc_target_bitrate = width * height * config.rc_target_bitrate
      / config.g_w / config.g_h;
  config.g_w = width;
  config.g_h = height;
  config.g_pass = VPX_RC_ONE_PASS;
  config.g_profile = 1;
  config.g_threads = 2;
  config.rc_min_quantizer = 0;
  config.rc_max_quantizer = 15;
  config.g_timebase.num = 1;
  config.g_timebase.den = 30;

  if (vpx_codec_enc_init(codec_.get(), algo, &config, 0))
    return false;
  return true;
}

static int clip_byte(int x) {
  if (x > 255)
    return 255;
  else if (x < 0)
    return 0;
  else
    return x;
}

bool EncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data) {
  const int plane_size = capture_data->width() * capture_data->height();

  if (!yuv_image_.get()) {

    // YUV image size is 1.5 times of a plane. Multiplication is performed first
    // to avoid rounding error.
    const int size = plane_size * 3 / 2;

    yuv_image_.reset(new uint8[size]);

    // Reset image value to 128 so we just need to fill in the y plane.
    memset(yuv_image_.get(), 128, size);

    // Fill in the information for |image_|.
    unsigned char* image = reinterpret_cast<unsigned char*>(yuv_image_.get());
    image_->planes[0] = image;
    image_->planes[1] = image + plane_size;

    // The V plane starts from 1.25 of the plane size.
    image_->planes[2] = image + plane_size + plane_size / 4;

    // In YV12 Y plane has full width, UV plane has half width because of
    // subsampling.
    image_->stride[0] = image_->w;
    image_->stride[1] = image_->w / 2;
    image_->stride[2] = image_->w / 2;
  }

  // And then do RGB->YUV conversion.
  // Currently we just produce the Y channel as the average of RGB. This will
  // giv ae gray scale image after conversion.
  // TODO(sergeyu): Move this code to a separate routine.
  // TODO(sergeyu): Optimize this code.
  DCHECK(capture_data->pixel_format() == media::VideoFrame::RGB32)
      << "Only RGB32 is supported";
  uint8* in = capture_data->data_planes().data[0];
  const int in_stride = capture_data->data_planes().strides[0];
  uint8* y_out = yuv_image_.get();
  uint8* u_out = yuv_image_.get() + plane_size;
  uint8* v_out = yuv_image_.get() + plane_size + plane_size / 4;
  const int out_stride = image_->stride[0];
  for (int i = 0; i < capture_data->height(); ++i) {
    for (int j = 0; j < capture_data->width(); ++j) {
      // Since the input pixel format is RGB32, there are 4 bytes per pixel.
      uint8* pixel = in + 4 * j;
      y_out[j] = clip_byte(((pixel[0] * 66 + pixel[1] * 129 +
                             pixel[2] * 25 + 128) >> 8) + 16);
      if (i % 2 == 0 && j % 2 == 0) {
        u_out[j / 2] = clip_byte(((pixel[0] * -38 + pixel[1] * -74 +
                                   pixel[2] * 112 + 128) >> 8) + 128);
        v_out[j / 2] = clip_byte(((pixel[0] * 112 + pixel[1] * -94 +
                                   pixel[2] * -18 + 128) >> 8) + 128);
      }
    }
    in += in_stride;
    y_out += out_stride;
    if (i % 2 == 0) {
      u_out += out_stride / 2;
      v_out += out_stride / 2;
    }
  }
  return true;
}

void EncoderVp8::Encode(scoped_refptr<CaptureData> capture_data,
                        bool key_frame,
                        DataAvailableCallback* data_available_callback) {
  if (!initialized_) {
    bool ret = Init(capture_data->width(), capture_data->height());
    // TODO(hclam): Handle error better.
    DCHECK(ret) << "Initialization of encoder failed";
    initialized_ = ret;
  }

  if (!PrepareImage(capture_data)) {
    NOTREACHED() << "Can't image data for encoding";
  }

  // Do the actual encoding.
  vpx_codec_err_t ret = vpx_codec_encode(codec_.get(), image_.get(),
                                         last_timestamp_,
                                         1, 0, VPX_DL_REALTIME);
  DCHECK_EQ(ret, VPX_CODEC_OK)
      << "Encoding error: " << vpx_codec_err_to_string(ret) << "\n"
      << "Details: " << vpx_codec_error(codec_.get()) << "\n"
      << vpx_codec_error_detail(codec_.get());

  // TODO(hclam): fix this.
  last_timestamp_ += 100;

  // Read the encoded data.
  vpx_codec_iter_t iter = NULL;
  bool got_data = false;

  // TODO(hclam): Make sure we get exactly one frame from the packet.
  // TODO(hclam): We should provide the output buffer to avoid one copy.
  VideoPacket* message = new VideoPacket();

  while (!got_data) {
    const vpx_codec_cx_pkt_t* packet = vpx_codec_get_cx_data(codec_.get(),
                                                             &iter);
    if (!packet)
      continue;

    switch (packet->kind) {
      case VPX_CODEC_CX_FRAME_PKT:
        got_data = true;
        message->set_data(packet->data.frame.buf, packet->data.frame.sz);
        break;
      default:
        break;
    }
  }

  message->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8);
  message->set_flags(VideoPacket::FIRST_PACKET | VideoPacket::LAST_PACKET);

  data_available_callback->Run(message);
  delete data_available_callback;
}

}  // namespace remoting
<commit_msg>Refactor ZLib and Verbatim encoders.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/logging.h"
#include "media/base/callback.h"
#include "media/base/media.h"
#include "remoting/base/capture_data.h"
#include "remoting/base/encoder_vp8.h"
#include "remoting/proto/video.pb.h"

extern "C" {
#define VPX_CODEC_DISABLE_COMPAT 1
#include "third_party/libvpx/include/vpx/vpx_codec.h"
#include "third_party/libvpx/include/vpx/vpx_encoder.h"
#include "third_party/libvpx/include/vpx/vp8cx.h"
}

namespace remoting {

EncoderVp8::EncoderVp8()
    : initialized_(false),
      codec_(NULL),
      image_(NULL),
      last_timestamp_(0) {
}

EncoderVp8::~EncoderVp8() {
  if (initialized_) {
    vpx_codec_err_t ret = vpx_codec_destroy(codec_.get());
    DCHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec";
  }
}

bool EncoderVp8::Init(int width, int height) {
  codec_.reset(new vpx_codec_ctx_t());
  image_.reset(new vpx_image_t());
  memset(image_.get(), 0, sizeof(vpx_image_t));

  image_->fmt = VPX_IMG_FMT_YV12;

  // libvpx seems to require both to be assigned.
  image_->d_w = width;
  image_->w = width;
  image_->d_h = height;
  image_->h = height;

  vpx_codec_enc_cfg_t config;
  const vpx_codec_iface_t* algo =
      (const vpx_codec_iface_t*)media::GetVp8CxAlgoAddress();
  CHECK(algo);
  vpx_codec_err_t ret = vpx_codec_enc_config_default(algo, &config, 0);
  if (ret != VPX_CODEC_OK)
    return false;

  // TODO(hclam): Tune the parameters to better suit the application.
  config.rc_target_bitrate = width * height * config.rc_target_bitrate
      / config.g_w / config.g_h;
  config.g_w = width;
  config.g_h = height;
  config.g_pass = VPX_RC_ONE_PASS;
  config.g_profile = 1;
  config.g_threads = 2;
  config.rc_min_quantizer = 0;
  config.rc_max_quantizer = 15;
  config.g_timebase.num = 1;
  config.g_timebase.den = 30;

  if (vpx_codec_enc_init(codec_.get(), algo, &config, 0))
    return false;
  return true;
}

static int clip_byte(int x) {
  if (x > 255)
    return 255;
  else if (x < 0)
    return 0;
  else
    return x;
}

bool EncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data) {
  const int plane_size = capture_data->width() * capture_data->height();

  if (!yuv_image_.get()) {

    // YUV image size is 1.5 times of a plane. Multiplication is performed first
    // to avoid rounding error.
    const int size = plane_size * 3 / 2;

    yuv_image_.reset(new uint8[size]);

    // Reset image value to 128 so we just need to fill in the y plane.
    memset(yuv_image_.get(), 128, size);

    // Fill in the information for |image_|.
    unsigned char* image = reinterpret_cast<unsigned char*>(yuv_image_.get());
    image_->planes[0] = image;
    image_->planes[1] = image + plane_size;

    // The V plane starts from 1.25 of the plane size.
    image_->planes[2] = image + plane_size + plane_size / 4;

    // In YV12 Y plane has full width, UV plane has half width because of
    // subsampling.
    image_->stride[0] = image_->w;
    image_->stride[1] = image_->w / 2;
    image_->stride[2] = image_->w / 2;
  }

  // And then do RGB->YUV conversion.
  // Currently we just produce the Y channel as the average of RGB. This will
  // giv ae gray scale image after conversion.
  // TODO(sergeyu): Move this code to a separate routine.
  // TODO(sergeyu): Optimize this code.
  DCHECK(capture_data->pixel_format() == media::VideoFrame::RGB32)
      << "Only RGB32 is supported";
  uint8* in = capture_data->data_planes().data[0];
  const int in_stride = capture_data->data_planes().strides[0];
  uint8* y_out = yuv_image_.get();
  uint8* u_out = yuv_image_.get() + plane_size;
  uint8* v_out = yuv_image_.get() + plane_size + plane_size / 4;
  const int out_stride = image_->stride[0];
  for (int i = 0; i < capture_data->height(); ++i) {
    for (int j = 0; j < capture_data->width(); ++j) {
      // Since the input pixel format is RGB32, there are 4 bytes per pixel.
      uint8* pixel = in + 4 * j;
      y_out[j] = clip_byte(((pixel[2] * 66 + pixel[1] * 129 +
                             pixel[0] * 25 + 128) >> 8) + 16);
      if (i % 2 == 0 && j % 2 == 0) {
        u_out[j / 2] = clip_byte(((pixel[2] * -38 + pixel[1] * -74 +
                                   pixel[0] * 112 + 128) >> 8) + 128);
        v_out[j / 2] = clip_byte(((pixel[2] * 112 + pixel[1] * -94 +
                                   pixel[1] * -18 + 128) >> 8) + 128);
      }
    }
    in += in_stride;
    y_out += out_stride;
    if (i % 2 == 0) {
      u_out += out_stride / 2;
      v_out += out_stride / 2;
    }
  }
  return true;
}

void EncoderVp8::Encode(scoped_refptr<CaptureData> capture_data,
                        bool key_frame,
                        DataAvailableCallback* data_available_callback) {
  if (!initialized_) {
    bool ret = Init(capture_data->width(), capture_data->height());
    // TODO(hclam): Handle error better.
    DCHECK(ret) << "Initialization of encoder failed";
    initialized_ = ret;
  }

  if (!PrepareImage(capture_data)) {
    NOTREACHED() << "Can't image data for encoding";
  }

  // Do the actual encoding.
  vpx_codec_err_t ret = vpx_codec_encode(codec_.get(), image_.get(),
                                         last_timestamp_,
                                         1, 0, VPX_DL_REALTIME);
  DCHECK_EQ(ret, VPX_CODEC_OK)
      << "Encoding error: " << vpx_codec_err_to_string(ret) << "\n"
      << "Details: " << vpx_codec_error(codec_.get()) << "\n"
      << vpx_codec_error_detail(codec_.get());

  // TODO(hclam): fix this.
  last_timestamp_ += 100;

  // Read the encoded data.
  vpx_codec_iter_t iter = NULL;
  bool got_data = false;

  // TODO(hclam): Make sure we get exactly one frame from the packet.
  // TODO(hclam): We should provide the output buffer to avoid one copy.
  VideoPacket* message = new VideoPacket();

  while (!got_data) {
    const vpx_codec_cx_pkt_t* packet = vpx_codec_get_cx_data(codec_.get(),
                                                             &iter);
    if (!packet)
      continue;

    switch (packet->kind) {
      case VPX_CODEC_CX_FRAME_PKT:
        got_data = true;
        message->set_data(packet->data.frame.buf, packet->data.frame.sz);
        break;
      default:
        break;
    }
  }

  message->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8);
  message->set_flags(VideoPacket::FIRST_PACKET | VideoPacket::LAST_PACKET);

  data_available_callback->Run(message);
  delete data_available_callback;
}

}  // namespace remoting
<|endoftext|>


<commit_before>/*

 Copyright (c) 2013, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the Ford Motor Company nor the names of its contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#include <string.h>
#include "application_manager/commands/mobile/perform_audio_pass_thru_request.h"
#include "application_manager/application_manager_impl.h"
#include "application_manager/application_impl.h"
#include "application_manager/message_helper.h"
#include "config_profile/profile.h"
#include "utils/helpers.h"

namespace application_manager {

namespace commands {

namespace str = strings;

PerformAudioPassThruRequest::PerformAudioPassThruRequest(
    const MessageSharedPtr& message)
    : CommandRequestImpl(message),
      is_active_tts_speak_(false),
      result_tts_speak_(mobile_apis::Result::SUCCESS) {
  subscribe_on_event(hmi_apis::FunctionID::TTS_OnResetTimeout);
}

PerformAudioPassThruRequest::~PerformAudioPassThruRequest() {
}

void PerformAudioPassThruRequest::onTimeOut() {
  LOG4CXX_AUTO_TRACE(logger_);

  FinishTTSSpeak();
  CommandRequestImpl::onTimeOut();
}

bool PerformAudioPassThruRequest::Init() {
  default_timeout_ +=
      (((*message_)[str::msg_params][str::max_duration].asUInt()));
  return true;
}

void PerformAudioPassThruRequest::Run() {
  LOG4CXX_AUTO_TRACE(logger_);

  ApplicationSharedPtr app =
      ApplicationManagerImpl::instance()->application(connection_key());

  if (!app) {
    LOG4CXX_ERROR(logger_, "APPLICATION_NOT_REGISTERED");
    SendResponse(false, mobile_apis::Result::APPLICATION_NOT_REGISTERED);
    return;
  }

  if (mobile_api::HMILevel::HMI_NONE == app->hmi_level()) {
    LOG4CXX_ERROR(logger_, "application isn't activated");
    SendResponse(false, mobile_apis::Result::REJECTED);
    return;
  }

  if (IsWhiteSpaceExist()) {
    LOG4CXX_ERROR(logger_,
                  "Incoming perform audio pass thru has contains "
                  "\\t\\n \\\\t \\\\n"
                  " text contains only whitespace in initialPrompt");
    SendResponse(false, mobile_apis::Result::INVALID_DATA);
    return;
  }

  if ((*message_)[str::msg_params].keyExists(str::initial_prompt) &&
      (0 < (*message_)[str::msg_params][str::initial_prompt].length())) {
    // In case TTS Speak, subscribe on notification
    SendSpeakRequest();
    SendPerformAudioPassThruRequest();
  } else {
    SendPerformAudioPassThruRequest();
    SendRecordStartNotification();
    StartMicrophoneRecording();
  }
}

void PerformAudioPassThruRequest::on_event(const event_engine::Event& event) {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace helpers;

  const smart_objects::SmartObject& message = event.smart_object();

  switch (event.id()) {
    case hmi_apis::FunctionID::UI_PerformAudioPassThru: {
      LOG4CXX_INFO(logger_, "Received UI_PerformAudioPassThru");

      if (!WaitTTSSpeak())
        return;

      mobile_apis::Result::eType mobile_code =
          GetMobileResultCode(static_cast<hmi_apis::Common_Result::eType>(
              message[strings::params][hmi_response::code].asUInt()));

      // in case perform audio is started by other request skip stopping
      if (mobile_apis::Result::REJECTED == mobile_code) {
        LOG4CXX_ERROR(logger_, "Request was rejected");
        SendResponse(false, mobile_code, NULL, &(message[strings::msg_params]));
        return;
      }

      FinishTTSSpeak();

      std::string return_info;
      const bool result =
          Compare<mobile_api::Result::eType, EQ, ONE>(
            mobile_code,
            mobile_apis::Result::SUCCESS,
            mobile_apis::Result::RETRY,
            mobile_apis::Result::WARNINGS);

      const bool is_result_ok =
          Compare<mobile_api::Result::eType, EQ, ONE>(
            mobile_code,
            mobile_apis::Result::SUCCESS,
            mobile_apis::Result::WARNINGS);

      if (is_result_ok &&
          mobile_apis::Result::UNSUPPORTED_RESOURCE == result_tts_speak_) {
        mobile_code = mobile_apis::Result::WARNINGS;
        return_info = "Unsupported phoneme type sent in a prompt";
      }

      SendResponse(result, mobile_code, return_info.c_str(),
                   &(message[strings::msg_params]));
      break;
    }
    case hmi_apis::FunctionID::TTS_Speak: {
      LOG4CXX_INFO(logger_, "Received TTS_Speak event");
      result_tts_speak_ = GetMobileResultCode(
            static_cast<hmi_apis::Common_Result::eType>(
          message[strings::params][hmi_response::code].asUInt()));
      is_active_tts_speak_ = false;
      if (mobile_apis::Result::SUCCESS == result_tts_speak_) {
        SendRecordStartNotification();
        StartMicrophoneRecording();

        // update request timeout to get time for perform audio recording
        ApplicationManagerImpl::instance()->
            updateRequestTimeout(connection_key(),
                                 correlation_id(),
                                 default_timeout());
      }
      break;
    }
    case hmi_apis::FunctionID::TTS_OnResetTimeout: {
      LOG4CXX_INFO(logger_, "Received TTS_OnResetTimeout event");

      ApplicationManagerImpl::instance()->updateRequestTimeout(
          connection_key(), correlation_id(), default_timeout());
      break;
    }
    default: {
      LOG4CXX_ERROR(logger_, "Received unknown event" << event.id());
      return;
    }
  }
}

void PerformAudioPassThruRequest::SendSpeakRequest() {
  LOG4CXX_AUTO_TRACE(logger_);

  using namespace hmi_apis;
  using namespace smart_objects;

  SmartObject msg_params = smart_objects::SmartObject(SmartType_Map);

  if ((*message_)[str::msg_params].keyExists(str::initial_prompt) &&
      (0 < (*message_)[str::msg_params][str::initial_prompt].length())) {
    for (uint32_t i = 0;
        i < (*message_)[str::msg_params][str::initial_prompt].length();
        ++i) {
      msg_params[hmi_request::tts_chunks][i][str::text] =
          (*message_)[str::msg_params][str::initial_prompt][i][str::text];
      msg_params[hmi_request::tts_chunks][i][str::type] =
          (*message_)[str::msg_params][str::initial_prompt][i][str::type];
    }
    // app_id
    msg_params[strings::app_id] = connection_key();
    msg_params[hmi_request::speak_type] = Common_MethodName::AUDIO_PASS_THRU;
    is_active_tts_speak_ = true;
    SendHMIRequest(FunctionID::TTS_Speak, &msg_params, true);
  }
}

void PerformAudioPassThruRequest::SendPerformAudioPassThruRequest() {
  LOG4CXX_AUTO_TRACE(logger_);

  smart_objects::SmartObject msg_params = smart_objects::SmartObject(
      smart_objects::SmartType_Map);

  msg_params[str::app_id] = connection_key();

  msg_params[hmi_request::max_duration] =
      (*message_)[str::msg_params][str::max_duration];

  msg_params[hmi_request::audio_pass_display_texts] =
      smart_objects::SmartObject(smart_objects::SmartType_Array);

  if ((*message_)[str::msg_params].keyExists(str::audio_pass_display_text1)) {
    msg_params[hmi_request::audio_pass_display_texts]
               [0][hmi_request::field_name] = static_cast<int32_t>
    (hmi_apis::Common_TextFieldName::audioPassThruDisplayText1);
    msg_params[hmi_request::audio_pass_display_texts]
               [0][hmi_request::field_text] =
        (*message_)[str::msg_params][str::audio_pass_display_text1];
  }

  if ((*message_)[str::msg_params].keyExists(str::audio_pass_display_text2)) {
    msg_params[hmi_request::audio_pass_display_texts]
               [1][hmi_request::field_name] = static_cast<int32_t>
    (hmi_apis::Common_TextFieldName::audioPassThruDisplayText2);
    msg_params[hmi_request::audio_pass_display_texts]
               [1][hmi_request::field_text] =
        (*message_)[str::msg_params][str::audio_pass_display_text2];
  }

  if ((*message_)[str::msg_params].keyExists(str::mute_audio)) {
    msg_params[str::mute_audio] =
        (*message_)[str::msg_params][str::mute_audio].asBool();
  } else {
    // If omitted, the value is set to true
    msg_params[str::mute_audio] = true;
  }

  SendHMIRequest(hmi_apis::FunctionID::UI_PerformAudioPassThru,
                 &msg_params, true);
}

void PerformAudioPassThruRequest::SendRecordStartNotification() {
  LOG4CXX_AUTO_TRACE(logger_);

  smart_objects::SmartObject msg_params = smart_objects::SmartObject(
      smart_objects::SmartType_Map);
  msg_params[strings::app_id] = connection_key();

  CreateHMINotification(hmi_apis::FunctionID::UI_OnRecordStart, msg_params);
}

void PerformAudioPassThruRequest::StartMicrophoneRecording() {
  LOG4CXX_AUTO_TRACE(logger_);

  ApplicationManagerImpl::instance()->begin_audio_pass_thru();

  ApplicationManagerImpl::instance()->StartAudioPassThruThread(
      connection_key(), correlation_id(),
      (*message_)[str::msg_params][str::max_duration].asInt(),
      (*message_)[str::msg_params][str::sampling_rate].asInt(),
      (*message_)[str::msg_params][str::bits_per_sample].asInt(),
      (*message_)[str::msg_params][str::audio_type].asInt());
}

bool PerformAudioPassThruRequest::IsWhiteSpaceExist() {
  LOG4CXX_AUTO_TRACE(logger_);
  const char* str = NULL;

  if ((*message_)[strings::msg_params].keyExists(strings::initial_prompt)) {
    const smart_objects::SmartArray* ip_array =
        (*message_)[strings::msg_params][strings::initial_prompt].asArray();

    smart_objects::SmartArray::const_iterator it_ip = ip_array->begin();
    smart_objects::SmartArray::const_iterator it_ip_end = ip_array->end();

    for (; it_ip != it_ip_end; ++it_ip) {
      str = (*it_ip)[strings::text].asCharArray();
      if (strlen(str) && !CheckSyntax(str)) {
        LOG4CXX_ERROR(logger_, "Invalid initial_prompt syntax check failed");
        return true;
      }
    }
  }

  if ((*message_)[strings::msg_params].
      keyExists(strings::audio_pass_display_text1)) {

    str = (*message_)[strings::msg_params]
                     [strings::audio_pass_display_text1].asCharArray();
    if (!CheckSyntax(str)) {
      LOG4CXX_ERROR(logger_,
          "Invalid audio_pass_display_text1 value syntax check failed");
      return true;
    }
  }

  if ((*message_)[strings::msg_params].
      keyExists(strings::audio_pass_display_text2)) {

    str = (*message_)[strings::msg_params]
                     [strings::audio_pass_display_text2].asCharArray();
    if (!CheckSyntax(str)) {
      LOG4CXX_ERROR(logger_,
          "Invalid audio_pass_display_text2 value syntax check failed");
      return true;
    }
  }
  return false;
}

void PerformAudioPassThruRequest::FinishTTSSpeak(){
  LOG4CXX_AUTO_TRACE(logger_);
  if (ApplicationManagerImpl::instance()->end_audio_pass_thru()) {
    ApplicationManagerImpl::instance()->
        StopAudioPassThru(connection_key());
  }
  if (!is_active_tts_speak_) {
    LOG4CXX_DEBUG(logger_, "TTS Speak is inactive.");
    return;
  }
  is_active_tts_speak_ = false;
  SendHMIRequest(hmi_apis::FunctionID::TTS_StopSpeaking, NULL);
}

bool PerformAudioPassThruRequest::WaitTTSSpeak() {
  LOG4CXX_AUTO_TRACE(logger_);
  uint32_t default_timeout_msec =
      profile::Profile::instance()->default_timeout();
  TimevalStruct start_time = date_time::DateTime::getCurrentTime();

  // Waiting for TTS_Speak
  while (is_active_tts_speak_) {
    int64_t difference_between_start_current_time
        = date_time::DateTime::calculateTimeSpan(start_time);
    // Send GENERIC_ERROR after default timeout
    if (difference_between_start_current_time > default_timeout_msec) {
      LOG4CXX_ERROR(logger_, "Expired timeout for TTS.Speak response");
      // Don't using onTimeOut(), becouse there default time is bigger than
      // Default time in *.ini file
      FinishTTSSpeak();
      SendResponse(false, mobile_apis::Result::eType::GENERIC_ERROR,
        "Expired timeout for TTS.Speak response");
      return false;
    }
  }
  return true;
}

}  // namespace commands

}  // namespace application_manager
<commit_msg>Add logs to WaitTTSSpeak method.<commit_after>/*

 Copyright (c) 2013, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the Ford Motor Company nor the names of its contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#include "application_manager/commands/mobile/perform_audio_pass_thru_request.h"
#include "application_manager/application_manager_impl.h"
#include "application_manager/application_impl.h"
#include "application_manager/message_helper.h"
#include "config_profile/profile.h"
#include "utils/helpers.h"

namespace application_manager {

namespace commands {

namespace str = strings;

PerformAudioPassThruRequest::PerformAudioPassThruRequest(
    const MessageSharedPtr& message)
    : CommandRequestImpl(message),
      is_active_tts_speak_(false),
      result_tts_speak_(mobile_apis::Result::SUCCESS) {
  subscribe_on_event(hmi_apis::FunctionID::TTS_OnResetTimeout);
}

PerformAudioPassThruRequest::~PerformAudioPassThruRequest() {
}

void PerformAudioPassThruRequest::onTimeOut() {
  LOG4CXX_AUTO_TRACE(logger_);

  FinishTTSSpeak();
  CommandRequestImpl::onTimeOut();
}

bool PerformAudioPassThruRequest::Init() {
  default_timeout_ +=
      (((*message_)[str::msg_params][str::max_duration].asUInt()));
  return true;
}

void PerformAudioPassThruRequest::Run() {
  LOG4CXX_AUTO_TRACE(logger_);

  ApplicationSharedPtr app =
      ApplicationManagerImpl::instance()->application(connection_key());

  if (!app) {
    LOG4CXX_ERROR(logger_, "APPLICATION_NOT_REGISTERED");
    SendResponse(false, mobile_apis::Result::APPLICATION_NOT_REGISTERED);
    return;
  }

  if (mobile_api::HMILevel::HMI_NONE == app->hmi_level()) {
    LOG4CXX_ERROR(logger_, "application isn't activated");
    SendResponse(false, mobile_apis::Result::REJECTED);
    return;
  }

  if (IsWhiteSpaceExist()) {
    LOG4CXX_ERROR(logger_,
                  "Incoming perform audio pass thru has contains "
                  "\\t\\n \\\\t \\\\n"
                  " text contains only whitespace in initialPrompt");
    SendResponse(false, mobile_apis::Result::INVALID_DATA);
    return;
  }

  if ((*message_)[str::msg_params].keyExists(str::initial_prompt) &&
      (0 < (*message_)[str::msg_params][str::initial_prompt].length())) {
    // In case TTS Speak, subscribe on notification
    SendSpeakRequest();
    SendPerformAudioPassThruRequest();
  } else {
    SendPerformAudioPassThruRequest();
    SendRecordStartNotification();
    StartMicrophoneRecording();
  }
}

void PerformAudioPassThruRequest::on_event(const event_engine::Event& event) {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace helpers;

  const smart_objects::SmartObject& message = event.smart_object();

  switch (event.id()) {
    case hmi_apis::FunctionID::UI_PerformAudioPassThru: {
      LOG4CXX_INFO(logger_, "Received UI_PerformAudioPassThru");

      if (!WaitTTSSpeak()) {
        LOG4CXX_AUTO_TRACE(logger_);
        return;
      }

      mobile_apis::Result::eType mobile_code =
          GetMobileResultCode(static_cast<hmi_apis::Common_Result::eType>(
              message[strings::params][hmi_response::code].asUInt()));

      // in case perform audio is started by other request skip stopping
      if (mobile_apis::Result::REJECTED == mobile_code) {
        LOG4CXX_ERROR(logger_, "Request was rejected");
        SendResponse(false, mobile_code, NULL, &(message[strings::msg_params]));
        return;
      }

      FinishTTSSpeak();

      std::string return_info;
      const bool result =
          Compare<mobile_api::Result::eType, EQ, ONE>(
            mobile_code,
            mobile_apis::Result::SUCCESS,
            mobile_apis::Result::RETRY,
            mobile_apis::Result::WARNINGS);

      const bool is_result_ok =
          Compare<mobile_api::Result::eType, EQ, ONE>(
            mobile_code,
            mobile_apis::Result::SUCCESS,
            mobile_apis::Result::WARNINGS);

      if (is_result_ok &&
          mobile_apis::Result::UNSUPPORTED_RESOURCE == result_tts_speak_) {
        mobile_code = mobile_apis::Result::WARNINGS;
        return_info = "Unsupported phoneme type sent in a prompt";
      }

      SendResponse(result, mobile_code, return_info.c_str(),
                   &(message[strings::msg_params]));
      break;
    }
    case hmi_apis::FunctionID::TTS_Speak: {
      LOG4CXX_INFO(logger_, "Received TTS_Speak event");
      result_tts_speak_ = GetMobileResultCode(
            static_cast<hmi_apis::Common_Result::eType>(
          message[strings::params][hmi_response::code].asUInt()));
      is_active_tts_speak_ = false;
      if (mobile_apis::Result::SUCCESS == result_tts_speak_) {
        SendRecordStartNotification();
        StartMicrophoneRecording();

        // update request timeout to get time for perform audio recording
        ApplicationManagerImpl::instance()->
            updateRequestTimeout(connection_key(),
                                 correlation_id(),
                                 default_timeout());
      }
      break;
    }
    case hmi_apis::FunctionID::TTS_OnResetTimeout: {
      LOG4CXX_INFO(logger_, "Received TTS_OnResetTimeout event");

      ApplicationManagerImpl::instance()->updateRequestTimeout(
          connection_key(), correlation_id(), default_timeout());
      break;
    }
    default: {
      LOG4CXX_ERROR(logger_, "Received unknown event" << event.id());
      return;
    }
  }
}

void PerformAudioPassThruRequest::SendSpeakRequest() {
  LOG4CXX_AUTO_TRACE(logger_);

  using namespace hmi_apis;
  using namespace smart_objects;

  SmartObject msg_params = smart_objects::SmartObject(SmartType_Map);

  if ((*message_)[str::msg_params].keyExists(str::initial_prompt) &&
      (0 < (*message_)[str::msg_params][str::initial_prompt].length())) {
    for (uint32_t i = 0;
        i < (*message_)[str::msg_params][str::initial_prompt].length();
        ++i) {
      msg_params[hmi_request::tts_chunks][i][str::text] =
          (*message_)[str::msg_params][str::initial_prompt][i][str::text];
      msg_params[hmi_request::tts_chunks][i][str::type] =
          (*message_)[str::msg_params][str::initial_prompt][i][str::type];
    }
    // app_id
    msg_params[strings::app_id] = connection_key();
    msg_params[hmi_request::speak_type] = Common_MethodName::AUDIO_PASS_THRU;
    is_active_tts_speak_ = true;
    SendHMIRequest(FunctionID::TTS_Speak, &msg_params, true);
  }
}

void PerformAudioPassThruRequest::SendPerformAudioPassThruRequest() {
  LOG4CXX_AUTO_TRACE(logger_);

  smart_objects::SmartObject msg_params = smart_objects::SmartObject(
      smart_objects::SmartType_Map);

  msg_params[str::app_id] = connection_key();

  msg_params[hmi_request::max_duration] =
      (*message_)[str::msg_params][str::max_duration];

  msg_params[hmi_request::audio_pass_display_texts] =
      smart_objects::SmartObject(smart_objects::SmartType_Array);

  if ((*message_)[str::msg_params].keyExists(str::audio_pass_display_text1)) {
    msg_params[hmi_request::audio_pass_display_texts]
               [0][hmi_request::field_name] = static_cast<int32_t>
    (hmi_apis::Common_TextFieldName::audioPassThruDisplayText1);
    msg_params[hmi_request::audio_pass_display_texts]
               [0][hmi_request::field_text] =
        (*message_)[str::msg_params][str::audio_pass_display_text1];
  }

  if ((*message_)[str::msg_params].keyExists(str::audio_pass_display_text2)) {
    msg_params[hmi_request::audio_pass_display_texts]
               [1][hmi_request::field_name] = static_cast<int32_t>
    (hmi_apis::Common_TextFieldName::audioPassThruDisplayText2);
    msg_params[hmi_request::audio_pass_display_texts]
               [1][hmi_request::field_text] =
        (*message_)[str::msg_params][str::audio_pass_display_text2];
  }

  if ((*message_)[str::msg_params].keyExists(str::mute_audio)) {
    msg_params[str::mute_audio] =
        (*message_)[str::msg_params][str::mute_audio].asBool();
  } else {
    // If omitted, the value is set to true
    msg_params[str::mute_audio] = true;
  }

  SendHMIRequest(hmi_apis::FunctionID::UI_PerformAudioPassThru,
                 &msg_params, true);
}

void PerformAudioPassThruRequest::SendRecordStartNotification() {
  LOG4CXX_AUTO_TRACE(logger_);

  smart_objects::SmartObject msg_params = smart_objects::SmartObject(
      smart_objects::SmartType_Map);
  msg_params[strings::app_id] = connection_key();

  CreateHMINotification(hmi_apis::FunctionID::UI_OnRecordStart, msg_params);
}

void PerformAudioPassThruRequest::StartMicrophoneRecording() {
  LOG4CXX_AUTO_TRACE(logger_);

  ApplicationManagerImpl::instance()->begin_audio_pass_thru();

  ApplicationManagerImpl::instance()->StartAudioPassThruThread(
      connection_key(), correlation_id(),
      (*message_)[str::msg_params][str::max_duration].asInt(),
      (*message_)[str::msg_params][str::sampling_rate].asInt(),
      (*message_)[str::msg_params][str::bits_per_sample].asInt(),
      (*message_)[str::msg_params][str::audio_type].asInt());
}

bool PerformAudioPassThruRequest::IsWhiteSpaceExist() {
  LOG4CXX_AUTO_TRACE(logger_);
  const char* str = NULL;

  if ((*message_)[strings::msg_params].keyExists(strings::initial_prompt)) {
    const smart_objects::SmartArray* ip_array =
        (*message_)[strings::msg_params][strings::initial_prompt].asArray();

    smart_objects::SmartArray::const_iterator it_ip = ip_array->begin();
    smart_objects::SmartArray::const_iterator it_ip_end = ip_array->end();

    for (; it_ip != it_ip_end; ++it_ip) {
      str = (*it_ip)[strings::text].asCharArray();
      if (strlen(str) && !CheckSyntax(str)) {
        LOG4CXX_ERROR(logger_, "Invalid initial_prompt syntax check failed");
        return true;
      }
    }
  }

  if ((*message_)[strings::msg_params].
      keyExists(strings::audio_pass_display_text1)) {

    str = (*message_)[strings::msg_params]
                     [strings::audio_pass_display_text1].asCharArray();
    if (!CheckSyntax(str)) {
      LOG4CXX_ERROR(logger_,
          "Invalid audio_pass_display_text1 value syntax check failed");
      return true;
    }
  }

  if ((*message_)[strings::msg_params].
      keyExists(strings::audio_pass_display_text2)) {

    str = (*message_)[strings::msg_params]
                     [strings::audio_pass_display_text2].asCharArray();
    if (!CheckSyntax(str)) {
      LOG4CXX_ERROR(logger_,
          "Invalid audio_pass_display_text2 value syntax check failed");
      return true;
    }
  }
  return false;
}

void PerformAudioPassThruRequest::FinishTTSSpeak() {
  LOG4CXX_AUTO_TRACE(logger_);
  if (ApplicationManagerImpl::instance()->end_audio_pass_thru()) {
    LOG4CXX_DEBUG(logger_, "Stop AudioPassThru.");
    ApplicationManagerImpl::instance()->
        StopAudioPassThru(connection_key());
  }
  if (!is_active_tts_speak_) {
    LOG4CXX_DEBUG(logger_, "TTS Speak is inactive.");
    return;
  }
  is_active_tts_speak_ = false;
  SendHMIRequest(hmi_apis::FunctionID::TTS_StopSpeaking, NULL);
}

bool PerformAudioPassThruRequest::WaitTTSSpeak() {
  LOG4CXX_AUTO_TRACE(logger_);
  uint64_t default_timeout_msec =
      profile::Profile::instance()->default_timeout();
  const TimevalStruct start_time = date_time::DateTime::getCurrentTime();

  // Waiting for TTS_Speak
  while (is_active_tts_speak_) {
    uint64_t difference_between_start_current_time
        = date_time::DateTime::calculateTimeSpan(start_time);
    // Send GENERIC_ERROR after default timeout
    if (difference_between_start_current_time > default_timeout_msec) {
      LOG4CXX_WARN(logger_, "Expired timeout for TTS.Speak response");
      // Don't use onTimeOut(), becouse default_timeout_ is bigger than
      // Default time in *.ini file
      FinishTTSSpeak();
      SendResponse(false, mobile_apis::Result::eType::GENERIC_ERROR,
        "Expired timeout for TTS.Speak response");
      return false;
    }
  }
  return true;
}

}  // namespace commands

}  // namespace application_manager
<|endoftext|>


<commit_before>/*==================================================

   Flexbar - flexible barcode and adapter removal

   Version 3.0.2

   uses SeqAn library release 2.2.0
   and TBB library 4.0 or later

             Developer:  Johannes Roehr

   Former contributors:  Matthias Dodt
                         Benjamin Menkuec
                         Sebastian Roskosch

   https://github.com/seqan/flexbar

===================================================*/

#include "Flexbar.h"

int main(int argc, const char* argv[]){

	using namespace std;
	using namespace seqan;

	const string version = "3.0.2";
	const string date    = "May 2017";

	ArgumentParser parser("flexbar");

	defineOptions(parser, version, date);
	parseCmdLine(parser, version, argc, argv);

	Options o;

	initOptions(o, parser);
	loadOptions(o, parser);

	startComputation(o);

	return 0;
}
<commit_msg>Flexbar 3.0.3 release<commit_after>/*==================================================

   Flexbar - flexible barcode and adapter removal

   Version 3.0.3

   uses SeqAn library release 2.2.0
   and TBB library 4.0 or later

             Developer:  Johannes Roehr

   Former contributors:  Matthias Dodt
                         Benjamin Menkuec
                         Sebastian Roskosch

   https://github.com/seqan/flexbar

===================================================*/

#include "Flexbar.h"

int main(int argc, const char* argv[]){

	using namespace std;
	using namespace seqan;

	const string version = "3.0.3";
	const string date    = "May 2017";

	ArgumentParser parser("flexbar");

	defineOptions(parser, version, date);
	parseCmdLine(parser, version, argc, argv);

	Options o;

	initOptions(o, parser);
	loadOptions(o, parser);

	startComputation(o);

	return 0;
}
<|endoftext|>


<commit_before>/**
 * \file
 *
 * \brief Implements a way to build and deal with a backend
 *
 * \copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 *
 */

#include <merging/threewaymerge.hpp>

using namespace std;

namespace kdb
{

namespace tools
{

namespace merging
{

/**
 * @brief Determines if two keys are equal based on their GetString() values.
 * Returns true if they are equal. False if they are not.
 */
bool ThreeWayMerge::keyDataEqual(const Key& k1, const Key& k2)
{
	if (!k1 && k2) return false;
	if (k1 && !k2) return false;
	if (k1.getString () != k2.getString ())
	{
		return false;
	}
	return true;
}

bool ThreeWayMerge::keyMetaEqual(Key& k1, Key& k2)
{
	k1.rewindMeta ();
	Key currentMeta;
	while ((currentMeta = k1.nextMeta ()))
	{
		string metaName = currentMeta.getName ();
		if (!k2.hasMeta (metaName)) return false;
		if (currentMeta.getString () != k2.getMeta<std::string> (metaName)) return false;
	}

	k2.rewindMeta ();
	while ((currentMeta = k2.nextMeta ()))
	{
		string metaName = currentMeta.getName ();
		if (!k1.hasMeta (metaName)) return false;
		if (currentMeta.getString () != k1.getMeta<std::string> (metaName)) return false;
	}

	return true;
}

string ThreeWayMerge::rebasePath(const Key& key, const Key& oldParent,
		const Key& newParent)
{
	string oldPath = key.getFullName ();
	string relativePath = oldPath.substr (oldParent.getFullName ().length (),
			oldPath.length ());
	string newPath = newParent.getFullName () + relativePath;

	return newPath;
}

Key ThreeWayMerge::rebaseKey(const Key& key, const Key& oldParent,
		const Key& newParent)
{
	Key result = key.dup ();
	result.setName (rebasePath (key, oldParent, newParent));
	return result;
}

// TODO: compare metakeys
void ThreeWayMerge::automaticMerge(const MergeTask& task,
		MergeResult& mergeResult, bool reverseConflictMeta = false)
{
	Key our;
	cursor_t savedCursor = task.ours.getCursor ();
	task.ours.rewind ();

	while ((our = task.ours.next ()))
	{
		string theirLookup = rebasePath (our, task.ourParent, task.theirParent);
		Key theirLookupResult = task.theirs.lookup (theirLookup);
		Key mergeKey = rebaseKey (our, task.ourParent, task.mergeRoot);

		if (keyDataEqual (our, theirLookupResult))
		{
			// keydata matches, see if metakeys match
			if (keyMetaEqual (our, theirLookupResult))
			{
				mergeResult.addMergeKey (mergeKey);
			}
			else
			{
				// metakeys are different
				mergeResult.addConflict (mergeKey, META, META);
			}
		}
		else
		{
			string baseLookup = rebasePath (our, task.ourParent,
					task.baseParent);
			Key baseLookupResult = task.base.lookup (baseLookup);

			// check if the keys was newly added in ours
			if (baseLookupResult)
			{
				// the key exists in base, check if the key still exists in theirs
				if (theirLookupResult)
				{
					// check if only they modified it
					if (!keyDataEqual (our, baseLookupResult)
							&& keyDataEqual (theirLookupResult,
									baseLookupResult))
					{
						// the key was only modified in theirs, take their version
						mergeResult.addMergeKey (mergeKey);
					}
					else
					{
						// check if both modified it
						if (!keyDataEqual (our, baseLookupResult)
								&& !keyDataEqual (theirLookupResult,
										baseLookupResult))
						{
							// the key was modified on both sides
							mergeResult.addConflict (mergeKey, MODIFY, MODIFY);
						}
					}
				}
				else
				{
					// the key does not exist in theirs anymore, check if ours has modified it
					if (keyDataEqual (our, baseLookupResult))
					{
						// the key was deleted in theirs, and not modified in ours
						mergeResult.removeMergeKey (mergeKey);
					}
					else
					{
						// the key was deleted in theirs, but modified in ours
						if (!reverseConflictMeta)
							mergeResult.addConflict (mergeKey, MODIFY, DELETE);
						else
							mergeResult.addConflict (mergeKey, DELETE, MODIFY);

					}
				}
			}
			else
			{
				// the key does not exist in base, check if the key was added in theirs
				if (theirLookupResult)
				{
					// check if the key was added with the same value in theirs
					if (keyDataEqual (mergeKey, theirLookupResult))
					{
						// the key was added on both sides with the same value
						mergeResult.addMergeKey (mergeKey);
					}
					else
					{
						// the key was added on both sides with different values
						mergeResult.addConflict (mergeKey, ADD, ADD);
					}
				}
				else
				{
					// the key was only added to ours
					mergeResult.addMergeKey (mergeKey);
				}
			}
		}
	}

	task.ours.setCursor (savedCursor);
}

/**
 * Returns a keyset that is the result of a merge on two keysets (ours and theirs) using a base keyset as a refernece (a three-way merge).
 * If the merge function is unscuessful an empty KeySet will be returned.
 * This function is inteded as a full version for the kdb merge command or for  the C++ API.
 * It works by taking in three keysets, their parent keys and a parent key for where to store the merged KeySet.
 **/
MergeResult ThreeWayMerge::mergeKeySet(const MergeTask& task)
{

	MergeResult result;
	automaticMerge (task, result);
	automaticMerge (task.reverse (), result, true);
	return result;
}

/**
 *
 * Returns a keyset that is the result of a merge on two keysets (ours and theirs) using a base keyset as a refernece (a three-way merge).
 * If the merge function is unscuessful an empty KeySet will be returned.
 * This function is inteded as a basic version for the C++ API. It takes in three keysets and a parent key for where to store the merged keys.
 * It works by finidng the parent key for each keyset and then calling the more complex function above.
 **/
MergeResult ThreeWayMerge::mergeKeySet(const KeySet& base, const KeySet& ours,
		const KeySet& theirs, Key& mergeRoot)
{
	Key ourkey = ours.head ().dup ();
	Key theirkey = theirs.head ().dup ();
	Key basekey = base.head ().dup ();

	MergeResult merged = mergeKeySet (
			MergeTask (BaseMergeKeys (base, basekey),
					OurMergeKeys (ours, ourkey),
					TheirMergeKeys (theirs, theirkey), mergeRoot));

	return merged;
}

}
}
}
<commit_msg>Wrote comments for the ThreeWayMerge functions<commit_after>/**
 * \file
 *
 * \brief Implements a way to build and deal with a backend
 *
 * \copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 *
 */

#include <merging/threewaymerge.hpp>

using namespace std;

namespace kdb
{

namespace tools
{

namespace merging
{

/**
 * Determines if two keys are equal based on their string value
 * If one of the two keys is null, false is returned
 *
 * @param k1 the first key to be compared
 * @param k2 the second key to be compared
 * @return true if both keys are not null and have an
 * equal string value, false otherwise
 */
bool ThreeWayMerge::keyDataEqual(const Key& k1, const Key& k2)
{
	if (!k1 && k2) return false;
	if (k1 && !k2) return false;
	if (k1.getString () != k2.getString ())
	{
		return false;
	}
	return true;
}

/**
 * Determines if two keys have equal metadata
 *
 *
 * @param k1 the first key whose metadata should be compared
 * @param k2 the second key whose metadata should be compared
 * @return true if the keys have equal metadata, false otherwise
 */
bool ThreeWayMerge::keyMetaEqual(Key& k1, Key& k2)
{
	k1.rewindMeta ();
	Key currentMeta;
	while ((currentMeta = k1.nextMeta ()))
	{
		string metaName = currentMeta.getName ();
		if (!k2.hasMeta (metaName)) return false;
		if (currentMeta.getString () != k2.getMeta<std::string> (metaName)) return false;
	}

	k2.rewindMeta ();
	while ((currentMeta = k2.nextMeta ()))
	{
		string metaName = currentMeta.getName ();
		if (!k1.hasMeta (metaName)) return false;
		if (currentMeta.getString () != k1.getMeta<std::string> (metaName)) return false;
	}

	return true;
}

/**
 * Rebases the relative path of the passed key from the old parent
 * to the new parent and returns the new path.
 *
 * For example a key /user/example/config/key1 with the oldparent
 * /user/example and the new parent /user/newexample/newpath would
 * result in /user/newexample/newpath/config/key1
 *
 * @param key the key whose path should be rebased
 * @param oldParent the old parent of the key
 * @param newParent the new parent of the key
 * @return the rebased path
 */
string ThreeWayMerge::rebasePath(const Key& key, const Key& oldParent,
		const Key& newParent)
{
	string oldPath = key.getFullName ();
	string relativePath = oldPath.substr (oldParent.getFullName ().length (),
			oldPath.length ());
	string newPath = newParent.getFullName () + relativePath;

	return newPath;
}

/**
 * Rebases the supplied key from the old parent to the new parent.
 *
 * @see ThreeWayMerge::rebasePath
 * @param key the key to be rebased
 * @param oldParent the old parent of the key
 * @param newParent the new parent of the key
 * @return a rebased copy of the supplied key
 */
Key ThreeWayMerge::rebaseKey(const Key& key, const Key& oldParent,
		const Key& newParent)
{
	Key result = key.dup ();
	result.setName (rebasePath (key, oldParent, newParent));
	return result;
}

// TODO: compare metakeys
void ThreeWayMerge::automaticMerge(const MergeTask& task,
		MergeResult& mergeResult, bool reverseConflictMeta = false)
{
	Key our;
	cursor_t savedCursor = task.ours.getCursor ();
	task.ours.rewind ();

	while ((our = task.ours.next ()))
	{
		string theirLookup = rebasePath (our, task.ourParent, task.theirParent);
		Key theirLookupResult = task.theirs.lookup (theirLookup);
		Key mergeKey = rebaseKey (our, task.ourParent, task.mergeRoot);

		if (keyDataEqual (our, theirLookupResult))
		{
			// keydata matches, see if metakeys match
			if (keyMetaEqual (our, theirLookupResult))
			{
				mergeResult.addMergeKey (mergeKey);
			}
			else
			{
				// metakeys are different
				mergeResult.addConflict (mergeKey, META, META);
			}
		}
		else
		{
			string baseLookup = rebasePath (our, task.ourParent,
					task.baseParent);
			Key baseLookupResult = task.base.lookup (baseLookup);

			// check if the keys was newly added in ours
			if (baseLookupResult)
			{
				// the key exists in base, check if the key still exists in theirs
				if (theirLookupResult)
				{
					// check if only they modified it
					if (!keyDataEqual (our, baseLookupResult)
							&& keyDataEqual (theirLookupResult,
									baseLookupResult))
					{
						// the key was only modified in theirs, take their version
						mergeResult.addMergeKey (mergeKey);
					}
					else
					{
						// check if both modified it
						if (!keyDataEqual (our, baseLookupResult)
								&& !keyDataEqual (theirLookupResult,
										baseLookupResult))
						{
							// the key was modified on both sides
							mergeResult.addConflict (mergeKey, MODIFY, MODIFY);
						}
					}
				}
				else
				{
					// the key does not exist in theirs anymore, check if ours has modified it
					if (keyDataEqual (our, baseLookupResult))
					{
						// the key was deleted in theirs, and not modified in ours
						mergeResult.removeMergeKey (mergeKey);
					}
					else
					{
						// the key was deleted in theirs, but modified in ours
						if (!reverseConflictMeta)
							mergeResult.addConflict (mergeKey, MODIFY, DELETE);
						else
							mergeResult.addConflict (mergeKey, DELETE, MODIFY);

					}
				}
			}
			else
			{
				// the key does not exist in base, check if the key was added in theirs
				if (theirLookupResult)
				{
					// check if the key was added with the same value in theirs
					if (keyDataEqual (mergeKey, theirLookupResult))
					{
						// the key was added on both sides with the same value
						mergeResult.addMergeKey (mergeKey);
					}
					else
					{
						// the key was added on both sides with different values
						mergeResult.addConflict (mergeKey, ADD, ADD);
					}
				}
				else
				{
					// the key was only added to ours
					mergeResult.addMergeKey (mergeKey);
				}
			}
		}
	}

	task.ours.setCursor (savedCursor);
}

/**
 * Performs a threeway merge according to the supplied MergeTask. All merged keys will
 * be below the given mergeParent in the MergeTask. Found conflicts will be
 * reported in the MergeResult. Conflicts are below the mergeParent as well and
 * are not part of the mergedKeys.
 *
 * @see MergeTask
 * @see MergeResult
 *
 * @param task a MergeTask describing the intended merge oparation
 * @return a MergeResult that contains the merged keys as well as all found conflicts.
 *
 **/
MergeResult ThreeWayMerge::mergeKeySet(const MergeTask& task)
{

	MergeResult result;
	automaticMerge (task, result);
	automaticMerge (task.reverse (), result, true);
	return result;
}

/**
 * Performs a threeway merge based on the supplied KeySets. The result is the same
 * as for ThreeWayMerge::mergeKeySet(const MergeTask&). The first key (i.e. the shortest)
 * in each of the supplied KeySets is considered to be the corresponding parentKey.
 * This means that the parent key of each KeySet MUST be part of the KeySet.
 *
 * @see ThreeWayMerge::mergeKeySet(const MergeTask&)
 *
 * @param base the KeySet containing the base keys and the base parentKey
 * @param ours the KeySet containing our keys and our parentKey
 * @param theirs the KeySet containing their keys and their parentKey
 * @param meregRoot the parentKey for the merged keys
 * @return a MergeResult that contains the merged keys as well as all found conflicts.
 */
MergeResult ThreeWayMerge::mergeKeySet(const KeySet& base, const KeySet& ours,
		const KeySet& theirs, Key& mergeRoot)
{
	Key ourkey = ours.head ().dup ();
	Key theirkey = theirs.head ().dup ();
	Key basekey = base.head ().dup ();

	MergeResult merged = mergeKeySet (
			MergeTask (BaseMergeKeys (base, basekey),
					OurMergeKeys (ours, ourkey),
					TheirMergeKeys (theirs, theirkey), mergeRoot));

	return merged;
}

}
}
}
<|endoftext|>


<commit_before>#ifndef ITER_ACCUMULATE_H_
#define ITER_ACCUMULATE_H_

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>
#include <functional>
#include <type_traits>

namespace iter {

    //Forward declarations of Accumulator and accumulate
    template <typename Container, typename AccumulateFunc>
    class Accumulator;

    template <typename Container, typename AccumulateFunc>
    Accumulator<Container, AccumulateFunc> accumulate(
            Container&&, AccumulateFunc);

    template <typename T, typename AccumulateFunc>
    Accumulator<std::initializer_list<T>, AccumulateFunc> accumulate(
            std::initializer_list<T>, AccumulateFunc);

    template <typename Container, typename AccumulateFunc>
    class Accumulator {
        private:
            Container container;
            AccumulateFunc accumulate_func;

            friend Accumulator accumulate<Container, AccumulateFunc>(
                    Container&&, AccumulateFunc);

            template <typename T, typename AF>
            friend Accumulator<std::initializer_list<T>, AF> accumulate(
                    std::initializer_list<T>, AF);

            // AccumVal must be default constructible
            using AccumVal =
                typename std::remove_reference<
                    typename std::result_of<AccumulateFunc(
                            iterator_deref<Container>,
                            iterator_deref<Container>)>::type>::type;
            static_assert(
                    std::is_default_constructible<AccumVal>::value,
                    "Cannot accumulate a non-default constructible type");

            Accumulator(Container&& container, AccumulateFunc accumulate_func)
                : container(std::forward<Container>(container)),
                accumulate_func(accumulate_func)
            { }
        public:

            class Iterator
                : public std::iterator<std::input_iterator_tag, AccumVal>
            {
                private:
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> sub_end;
                    AccumulateFunc accumulate_func;
                    AccumVal acc_val;
                public:
                    Iterator (iterator_type<Container> iter,
                            iterator_type<Container> end,
                            AccumulateFunc accumulate_func)
                        : sub_iter{iter},
                        sub_end{end},
                        accumulate_func(accumulate_func),
                        // only get first value if not an end iterator
                        acc_val(!(iter != end) ? AccumVal{} : *iter)
                    { }

                    const AccumVal& operator*() const {
                        return this->acc_val;
                    }

                    Iterator& operator++() {
                        ++this->sub_iter;
                        if (this->sub_iter != this->sub_end) {
                            this->acc_val = accumulate_func(
                                    this->acc_val, *this->sub_iter);
                        }
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->sub_iter != other.sub_iter;
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }
            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container),
                        this->accumulate_func};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container),
                        this->accumulate_func};
            }

    };

    // Helper function to instantiate an Accumulator
    template <typename Container, typename AccumulateFunc>
    Accumulator<Container, AccumulateFunc> accumulate(
            Container&& container,
            AccumulateFunc accumulate_func)
    {
        return {std::forward<Container>(container), accumulate_func};
    }

    template <typename Container>
    auto accumulate(Container&& container) ->
        decltype(accumulate(std::forward<Container>(container),
                    std::plus<typename std::remove_reference<
                        iterator_deref<Container>>::type>{}))
    {
        return accumulate(std::forward<Container>(container),
                    std::plus<typename std::remove_reference<
                        iterator_deref<Container>>::type>{});
    }

    template <typename T, typename AccumulateFunc>
    Accumulator<std::initializer_list<T>, AccumulateFunc> accumulate(
            std::initializer_list<T> il,
            AccumulateFunc accumulate_func)
    {
        return {std::move(il), accumulate_func};
    }

    template <typename T>
    auto accumulate(std::initializer_list<T> il) ->
        decltype(accumulate(std::move(il), std::plus<T>{}))
    {
        return accumulate(std::move(il), std::plus<T>{});
    }

}

#endif
<commit_msg>uses c++14 type aliases<commit_after>#ifndef ITER_ACCUMULATE_H_
#define ITER_ACCUMULATE_H_

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>
#include <functional>
#include <type_traits>

namespace iter {

    //Forward declarations of Accumulator and accumulate
    template <typename Container, typename AccumulateFunc>
    class Accumulator;

    template <typename Container, typename AccumulateFunc>
    Accumulator<Container, AccumulateFunc> accumulate(
            Container&&, AccumulateFunc);

    template <typename T, typename AccumulateFunc>
    Accumulator<std::initializer_list<T>, AccumulateFunc> accumulate(
            std::initializer_list<T>, AccumulateFunc);

    template <typename Container, typename AccumulateFunc>
    class Accumulator {
        private:
            Container container;
            AccumulateFunc accumulate_func;

            friend Accumulator accumulate<Container, AccumulateFunc>(
                    Container&&, AccumulateFunc);

            template <typename T, typename AF>
            friend Accumulator<std::initializer_list<T>, AF> accumulate(
                    std::initializer_list<T>, AF);

            // AccumVal must be default constructible
            using AccumVal =
                std::remove_reference_t<
                    std::result_of_t<AccumulateFunc(
                            iterator_deref<Container>,
                            iterator_deref<Container>)>>;
            static_assert(
                    std::is_default_constructible<AccumVal>::value,
                    "Cannot accumulate a non-default constructible type");

            Accumulator(Container&& container, AccumulateFunc accumulate_func)
                : container(std::forward<Container>(container)),
                accumulate_func(accumulate_func)
            { }
        public:

            class Iterator
                : public std::iterator<std::input_iterator_tag, AccumVal>
            {
                private:
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> sub_end;
                    AccumulateFunc accumulate_func;
                    AccumVal acc_val;
                public:
                    Iterator (iterator_type<Container> iter,
                            iterator_type<Container> end,
                            AccumulateFunc accumulate_func)
                        : sub_iter{iter},
                        sub_end{end},
                        accumulate_func(accumulate_func),
                        // only get first value if not an end iterator
                        acc_val(!(iter != end) ? AccumVal{} : *iter)
                    { }

                    const AccumVal& operator*() const {
                        return this->acc_val;
                    }

                    Iterator& operator++() {
                        ++this->sub_iter;
                        if (this->sub_iter != this->sub_end) {
                            this->acc_val = accumulate_func(
                                    this->acc_val, *this->sub_iter);
                        }
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->sub_iter != other.sub_iter;
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }
            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container),
                        this->accumulate_func};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container),
                        this->accumulate_func};
            }

    };

    // Helper function to instantiate an Accumulator
    template <typename Container, typename AccumulateFunc>
    Accumulator<Container, AccumulateFunc> accumulate(
            Container&& container,
            AccumulateFunc accumulate_func)
    {
        return {std::forward<Container>(container), accumulate_func};
    }

    template <typename Container>
    auto accumulate(Container&& container) ->
        decltype(accumulate(std::forward<Container>(container),
                    std::plus<std::remove_reference_t<
                        iterator_deref<Container>>>{}))
    {
        return accumulate(std::forward<Container>(container),
                    std::plus<std::remove_reference_t<
                        iterator_deref<Container>>>{});
    }

    template <typename T, typename AccumulateFunc>
    Accumulator<std::initializer_list<T>, AccumulateFunc> accumulate(
            std::initializer_list<T> il,
            AccumulateFunc accumulate_func)
    {
        return {std::move(il), accumulate_func};
    }

    template <typename T>
    auto accumulate(std::initializer_list<T> il) ->
        decltype(accumulate(std::move(il), std::plus<T>{}))
    {
        return accumulate(std::move(il), std::plus<T>{});
    }

}

#endif
<|endoftext|>


<commit_before>#include "writer/CoutWriter.hpp"
#include "fmi/ValueInfo.hpp"

namespace Writer
{

    CoutWriter::CoutWriter(const Initialization::WriterPlan & in)
            : IWriter(in), _lineEndingSign('\n'), _separator(',')
    {
        LOGGER_WRITE("Using CoutWriter", Util::LC_LOADER, Util::LL_INFO);

    }

    CoutWriter::~CoutWriter()
    {
        deinitialize();
    }

    void CoutWriter::initialize()
    {
        IWriter::initialize();
        if (std::cout.fail())
            throw runtime_error("Cannot create and open result file.");
    }

    void CoutWriter::deinitialize()
    {
        IWriter::deinitialize();
    }

    void CoutWriter::appendTimeHeader()
    {
        assert(isInitialized());
        std::cout << "time";
    }

    void CoutWriter::appendTime(double time)
    {
        assert(isInitialized());
        std::cout << _lineEndingSign << std::endl << time;
    }

    void CoutWriter::appendHeader(const string_type& fmuName, const FMI::ValueInfo& variables)
    {
        assert(isInitialized());
        for(string_type value : variables.getAllValueNames())
        {
            Util::StringHelper::replaceAll(value, ",", "_");
            std::cout << _separator << fmuName << "." << value;
        }
    }

    void CoutWriter::appendResults(const string_type& fmuName, const FMI::ValueCollection& values)
    {
        assert(isInitialized());
        for(real_type value : values.getValues<real_type>())
            std::cout << _separator << to_string(value);
        for(int_type value : values.getValues<int_type>())
            std::cout << _separator << to_string(value);
        for(bool_type value : values.getValues<bool_type>())
            std::cout << _separator << to_string(value);
        for(string_type value : values.getValues<string_type>())
            std::cout << _separator << "\"" << value << "\"";
    }

    void CoutWriter::flushResults()
    {
        assert(isInitialized());
        std::cout.flush();
    }

} /* namespace DataAccess */
<commit_msg>Cosmetic changes<commit_after>#include "writer/CoutWriter.hpp"
#include "fmi/ValueInfo.hpp"

namespace Writer
{

    CoutWriter::CoutWriter(const Initialization::WriterPlan & in)
            : IWriter(in),
              _lineEndingSign('\n'),
              _separator(',')
    {
        LOGGER_WRITE("Using CoutWriter", Util::LC_LOADER, Util::LL_INFO);

    }

    CoutWriter::~CoutWriter()
    {
        deinitialize();
    }

    void CoutWriter::initialize()
    {
        IWriter::initialize();
        if (std::cout.fail())
            throw runtime_error("Cannot create and open result file.");
    }

    void CoutWriter::deinitialize()
    {
        IWriter::deinitialize();
    }

    void CoutWriter::appendTimeHeader()
    {
        assert(isInitialized());
        std::cout << "time";
    }

    void CoutWriter::appendTime(double time)
    {
        assert(isInitialized());
        std::cout << _lineEndingSign << std::endl << time;
    }

    void CoutWriter::appendHeader(const string_type& fmuName, const FMI::ValueInfo& variables)
    {
        assert(isInitialized());
        for (string_type value : variables.getAllValueNames())
        {
            Util::StringHelper::replaceAll(value, ",", "_");
            std::cout << _separator << fmuName << "." << value;
        }
    }

    void CoutWriter::appendResults(const string_type& fmuName, const FMI::ValueCollection& values)
    {
        assert(isInitialized());
        for (real_type value : values.getValues<real_type>())
            std::cout << _separator << to_string(value);
        for (int_type value : values.getValues<int_type>())
            std::cout << _separator << to_string(value);
        for (bool_type value : values.getValues<bool_type>())
            std::cout << _separator << to_string(value);
        for (string_type value : values.getValues<string_type>())
            std::cout << _separator << "\"" << value << "\"";
    }

    void CoutWriter::flushResults()
    {
        assert(isInitialized());
        std::cout.flush();
    }

} /* namespace DataAccess */
<|endoftext|>


<commit_before>/*
Copyright 2013-present Barefoot Networks, Inc.

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 "analyzer.h"

#include "ir/ir.h"
#include "frontends/p4/fromv1.0/v1model.h"
#include "frontends/p4/typeMap.h"
#include "frontends/common/resolveReferences/referenceMap.h"
#include "frontends/p4/methodInstance.h"
#include "frontends/p4/tableApply.h"

namespace FPGA {

cstring nameFromAnnotation(const IR::Annotations* annotations,
                           cstring defaultValue) {
    CHECK_NULL(annotations); CHECK_NULL(defaultValue);
    auto anno = annotations->getSingle(IR::Annotation::nameAnnotation);
    if (anno != nullptr) {
        CHECK_NULL(anno->expr);
        auto str = anno->expr->to<IR::StringLiteral>();
        CHECK_NULL(str);
        return str->value;
    }
    return defaultValue;
}

unsigned CFG::Node::crtId = 0;

void CFG::EdgeSet::dbprint(std::ostream& out) const {
    for (auto s : edges)
        out << " " << s;
}

void CFG::Edge::dbprint(std::ostream& out) const {
    out << endpoint->name;
    switch (type) {
        case EdgeType::True:
            out << "(true)";
            break;
        case EdgeType::False:
            out << "(false)";
            break;
        case EdgeType::Label:
            out << "(" << label << ")";
            break;
        default:
            break;
    }
}

void CFG::Node::dbprint(std::ostream& out) const
{ out << name << " =>" << successors; }

void CFG::dbprint(std::ostream& out, CFG::Node* node, std::set<CFG::Node*> &done) const {
    if (done.find(node) != done.end())
        return;
    for (auto p : node->predecessors.edges)
        dbprint(out, p->endpoint, done);
    out << std::endl << node;
    done.emplace(node);
}

void CFG::dbprint(std::ostream& out) const {
    out << "CFG for " << container;
    std::set<CFG::Node*> done;
    for (auto n : allNodes)
        dbprint(out, n, done);
}

void CFG::Node::computeSuccessors() {
    for (auto e : predecessors.edges)
        e->getNode()->successors.emplace(e->clone(this));
}

namespace {
// This visitor "converts" IR::Node* into EdgeSets
// Since we cannot return EdgeSets, we place them in the 'after' map.
class CFGBuilder : public Inspector {
    CFG*                                           cfg;
    const CFG::EdgeSet*                            current;  // predecessors of current node
    std::map<const IR::Statement*, const CFG::EdgeSet*> after;  // successors of each statement
    const P4::ReferenceMap*                     refMap;
    const P4::TypeMap*                          typeMap;

    void setAfter(const IR::Statement* statement, const CFG::EdgeSet* value) {
        LOG1("After " << statement << " " << value);
        CHECK_NULL(statement);
        if (value == nullptr) {
            // This can happen when an error is signaled
            // one cause is assignmentStatement
            return;
        }
        after.emplace(statement, value);
        current = value;
    }

    const CFG::EdgeSet* get(const IR::Statement* statement) {
      return ::get(after, statement);
    }
    bool preorder(const IR::Statement* statement) override {
        //::error("%1%: not supported in control block on this architecture", statement);
        return false;
    }
    bool preorder(const IR::ReturnStatement* statement) override {
        if (current != nullptr) {
          cfg->exitPoint->addPredecessors(current);
        }
        setAfter(statement, new CFG::EdgeSet());  // empty successor set
        return false;
    }
    bool preorder(const IR::ExitStatement* statement) override {
        if (current != nullptr) {
          cfg->exitPoint->addPredecessors(current);
        }
        setAfter(statement, new CFG::EdgeSet());  // empty successor set
        return false;
    }
    bool preorder(const IR::EmptyStatement* statement) override {
        // unchanged 'current'
        setAfter(statement, current);
        return false;
    }
    bool preorder(const IR::MethodCallStatement* statement) override {
        auto instance = P4::MethodInstance::resolve(statement->methodCall, refMap, typeMap);
        if (!instance->is<P4::ApplyMethod>())
            return false;
        auto am = instance->to<P4::ApplyMethod>();
        if (!am->object->is<IR::P4Table>()) {
            ::error("%1%: apply method must be on a table", statement);
            return false;
        }
        auto tc = am->object->to<IR::P4Table>();
        LOG1("table << " << tc);
        auto node = cfg->makeNode(tc, statement->methodCall);
        if (current != nullptr) {
          node->addPredecessors(current);
        }
        setAfter(statement, new CFG::EdgeSet(new CFG::Edge(node)));
        return false;
    }
    bool preorder(const IR::IfStatement* statement) override {
        // We only allow expressions of the form t.apply().hit currently.
        // If the expression is more complex it should have been
        // simplified by prior passes.
        auto tc = P4::TableApplySolver::isHit(statement->condition, refMap, typeMap);
        CFG::Node* node;
        if (tc != nullptr) {
            // hit-miss case.
            LOG1("if << " << tc);
            node = cfg->makeNode(tc, statement->condition);
        } else {
            node = cfg->makeNode(statement);
        }

        if (current != nullptr) {
          node->addPredecessors(current);
        }
        // If branch
        current = new CFG::EdgeSet(new CFG::Edge(node, true));
        visit(statement->ifTrue);
        auto ifTrue = get(statement->ifTrue);
        if (ifTrue == nullptr)
            return false;
        auto result = new CFG::EdgeSet(ifTrue);

        // Else branch
        if (statement->ifFalse != nullptr) {
            current = new CFG::EdgeSet(new CFG::Edge(node, false));
            visit(statement->ifFalse);
            auto ifFalse = get(statement->ifFalse);
            if (ifFalse != nullptr) {
              result->mergeWith(ifFalse);
            }
        } else {
            // no else branch
            result->mergeWith(new CFG::EdgeSet(new CFG::Edge(node, false)));
        }
        setAfter(statement, result);
        return false;
    }
    bool preorder(const IR::BlockStatement* statement) override {
        for (auto s : *statement->components) {
            // NOTE: ignore AssignmentStatement, insert it to 'after' map will
            // break cfg.
            if (s->is<IR::AssignmentStatement>())
              continue;
            auto stat = s->to<IR::Statement>();
            if (stat == nullptr) continue;
            visit(stat);
            current = get(stat);
        }
        setAfter(statement, current);
        return false;
    }
    bool preorder(const IR::SwitchStatement* statement) override {
        auto tc = P4::TableApplySolver::isActionRun(statement->expression, refMap, typeMap);
        BUG_CHECK(tc != nullptr, "%1%: unexpected switch statement expression",
                  statement->expression);
        LOG1("switch << " << tc);
        auto node = cfg->makeNode(tc, statement->expression);
        if (current != nullptr) {
          node->addPredecessors(current);
        }
        auto result = new CFG::EdgeSet(new CFG::Edge(node));  // In case no label matches
        auto labels = new CFG::EdgeSet();
        for (auto sw : statement->cases) {
            cstring label;
            if (sw->label->is<IR::DefaultExpression>()) {
                label = "default";
            } else {
                auto pe = sw->label->to<IR::PathExpression>();
                CHECK_NULL(pe);
                label = pe->path->name.name;
            }
            labels->mergeWith(new CFG::EdgeSet(new CFG::Edge(node, label)));
            if (sw->statement != nullptr) {
                current = labels;
                visit(sw->statement);
                labels = new CFG::EdgeSet();
            }  // else we accumulate edges
            if (current != nullptr) {
              result->mergeWith(current);
            }
        }
        setAfter(statement, result);
        return false;
    }

 public:
    CFGBuilder(CFG* cfg, const P4::ReferenceMap* refMap, const P4::TypeMap* typeMap) :
            cfg(cfg), current(nullptr), refMap(refMap), typeMap(typeMap) {}
    const CFG::EdgeSet* run(const IR::Statement* startNode, const CFG::EdgeSet* predecessors) {
        CHECK_NULL(startNode); CHECK_NULL(predecessors);
        current = predecessors;
        LOG1("start " << startNode->node_type_name());
        LOG1("pred " << predecessors);
        startNode->apply(*this);
        return current;
    }
};
}  // end anonymous namespace

void CFG::build(const IR::P4Control* cc,
                const P4::ReferenceMap* refMap, const P4::TypeMap* typeMap) {
    container = cc;
    entryPoint = makeNode("entry");
    exitPoint = makeNode("exit");

    CFGBuilder builder(this, refMap, typeMap);
    auto startValue = new CFG::EdgeSet(new CFG::Edge(entryPoint));
    auto last = builder.run(cc->body, startValue);
    LOG1("Before exit " << last);
    if (last != nullptr) {
        // nullptr can happen when there is an error
        exitPoint->addPredecessors(last);
        computeSuccessors();
    }
}

namespace {
class DiscoverStructure : public Inspector {
    ProgramParts*           structure;

 public:
    explicit DiscoverStructure(ProgramParts* structure) : structure(structure) {}

    void postorder(const IR::ParameterList* paramList) override {
        bool inAction = findContext<IR::P4Action>() != nullptr;
        unsigned index = 0;
        for (auto p : *paramList->getEnumerator()) {
            structure->index.emplace(p, index);
            if (!inAction)
                structure->nonActionParameters.emplace(p);
            index++;
        }
    }
    void postorder(const IR::P4Action* action) override {
        auto control = findContext<IR::P4Control>();
        structure->actions.emplace(action, control);
    }
    void postorder(const IR::Declaration_Variable* decl) override {
        structure->variables.push_back(decl);
    }
};
}  // namespace

void ProgramParts::analyze(IR::ToplevelBlock* toplevel) {
    DiscoverStructure disc(this);
    toplevel->getProgram()->apply(disc);
}

}  // namespace FPGA
<commit_msg>make sure annotated name does not have '.'<commit_after>/*
Copyright 2013-present Barefoot Networks, Inc.

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 <string>
#include <algorithm>
#include "analyzer.h"

#include "ir/ir.h"
#include "frontends/p4/fromv1.0/v1model.h"
#include "frontends/p4/typeMap.h"
#include "frontends/common/resolveReferences/referenceMap.h"
#include "frontends/p4/methodInstance.h"
#include "frontends/p4/tableApply.h"

namespace FPGA {

cstring nameFromAnnotation(const IR::Annotations* annotations,
                           cstring defaultValue) {
    CHECK_NULL(annotations); CHECK_NULL(defaultValue);
    auto anno = annotations->getSingle(IR::Annotation::nameAnnotation);
    if (anno != nullptr) {
        CHECK_NULL(anno->expr);
        auto str = anno->expr->to<IR::StringLiteral>();
        CHECK_NULL(str);
        // NOTE: replace '.' with '_' to make bsc happy
        std::string name(str->value);
        std::replace(name.begin(), name.end(), '.', '_');
        return name.c_str();
    }
    return defaultValue;
}

unsigned CFG::Node::crtId = 0;

void CFG::EdgeSet::dbprint(std::ostream& out) const {
    for (auto s : edges)
        out << " " << s;
}

void CFG::Edge::dbprint(std::ostream& out) const {
    out << endpoint->name;
    switch (type) {
        case EdgeType::True:
            out << "(true)";
            break;
        case EdgeType::False:
            out << "(false)";
            break;
        case EdgeType::Label:
            out << "(" << label << ")";
            break;
        default:
            break;
    }
}

void CFG::Node::dbprint(std::ostream& out) const
{ out << name << " =>" << successors; }

void CFG::dbprint(std::ostream& out, CFG::Node* node, std::set<CFG::Node*> &done) const {
    if (done.find(node) != done.end())
        return;
    for (auto p : node->predecessors.edges)
        dbprint(out, p->endpoint, done);
    out << std::endl << node;
    done.emplace(node);
}

void CFG::dbprint(std::ostream& out) const {
    out << "CFG for " << container;
    std::set<CFG::Node*> done;
    for (auto n : allNodes)
        dbprint(out, n, done);
}

void CFG::Node::computeSuccessors() {
    for (auto e : predecessors.edges)
        e->getNode()->successors.emplace(e->clone(this));
}

namespace {
// This visitor "converts" IR::Node* into EdgeSets
// Since we cannot return EdgeSets, we place them in the 'after' map.
class CFGBuilder : public Inspector {
    CFG*                                           cfg;
    const CFG::EdgeSet*                            current;  // predecessors of current node
    std::map<const IR::Statement*, const CFG::EdgeSet*> after;  // successors of each statement
    const P4::ReferenceMap*                     refMap;
    const P4::TypeMap*                          typeMap;

    void setAfter(const IR::Statement* statement, const CFG::EdgeSet* value) {
        LOG1("After " << statement << " " << value);
        CHECK_NULL(statement);
        if (value == nullptr) {
            // This can happen when an error is signaled
            // one cause is assignmentStatement
            return;
        }
        after.emplace(statement, value);
        current = value;
    }

    const CFG::EdgeSet* get(const IR::Statement* statement) {
      return ::get(after, statement);
    }
    bool preorder(const IR::Statement* statement) override {
        //::error("%1%: not supported in control block on this architecture", statement);
        return false;
    }
    bool preorder(const IR::ReturnStatement* statement) override {
        if (current != nullptr) {
          cfg->exitPoint->addPredecessors(current);
        }
        setAfter(statement, new CFG::EdgeSet());  // empty successor set
        return false;
    }
    bool preorder(const IR::ExitStatement* statement) override {
        if (current != nullptr) {
          cfg->exitPoint->addPredecessors(current);
        }
        setAfter(statement, new CFG::EdgeSet());  // empty successor set
        return false;
    }
    bool preorder(const IR::EmptyStatement* statement) override {
        // unchanged 'current'
        setAfter(statement, current);
        return false;
    }
    bool preorder(const IR::MethodCallStatement* statement) override {
        auto instance = P4::MethodInstance::resolve(statement->methodCall, refMap, typeMap);
        if (!instance->is<P4::ApplyMethod>())
            return false;
        auto am = instance->to<P4::ApplyMethod>();
        if (!am->object->is<IR::P4Table>()) {
            ::error("%1%: apply method must be on a table", statement);
            return false;
        }
        auto tc = am->object->to<IR::P4Table>();
        LOG1("table << " << tc);
        auto node = cfg->makeNode(tc, statement->methodCall);
        if (current != nullptr) {
          node->addPredecessors(current);
        }
        setAfter(statement, new CFG::EdgeSet(new CFG::Edge(node)));
        return false;
    }
    bool preorder(const IR::IfStatement* statement) override {
        // We only allow expressions of the form t.apply().hit currently.
        // If the expression is more complex it should have been
        // simplified by prior passes.
        auto tc = P4::TableApplySolver::isHit(statement->condition, refMap, typeMap);
        CFG::Node* node;
        if (tc != nullptr) {
            // hit-miss case.
            LOG1("if << " << tc);
            node = cfg->makeNode(tc, statement->condition);
        } else {
            node = cfg->makeNode(statement);
        }

        if (current != nullptr) {
          node->addPredecessors(current);
        }
        // If branch
        current = new CFG::EdgeSet(new CFG::Edge(node, true));
        visit(statement->ifTrue);
        auto ifTrue = get(statement->ifTrue);
        if (ifTrue == nullptr)
            return false;
        auto result = new CFG::EdgeSet(ifTrue);

        // Else branch
        if (statement->ifFalse != nullptr) {
            current = new CFG::EdgeSet(new CFG::Edge(node, false));
            visit(statement->ifFalse);
            auto ifFalse = get(statement->ifFalse);
            if (ifFalse != nullptr) {
              result->mergeWith(ifFalse);
            }
        } else {
            // no else branch
            result->mergeWith(new CFG::EdgeSet(new CFG::Edge(node, false)));
        }
        setAfter(statement, result);
        return false;
    }
    bool preorder(const IR::BlockStatement* statement) override {
        for (auto s : *statement->components) {
            // NOTE: ignore AssignmentStatement, insert it to 'after' map will
            // break cfg.
            if (s->is<IR::AssignmentStatement>())
              continue;
            auto stat = s->to<IR::Statement>();
            if (stat == nullptr) continue;
            visit(stat);
            current = get(stat);
        }
        setAfter(statement, current);
        return false;
    }
    bool preorder(const IR::SwitchStatement* statement) override {
        auto tc = P4::TableApplySolver::isActionRun(statement->expression, refMap, typeMap);
        BUG_CHECK(tc != nullptr, "%1%: unexpected switch statement expression",
                  statement->expression);
        LOG1("switch << " << tc);
        auto node = cfg->makeNode(tc, statement->expression);
        if (current != nullptr) {
          node->addPredecessors(current);
        }
        auto result = new CFG::EdgeSet(new CFG::Edge(node));  // In case no label matches
        auto labels = new CFG::EdgeSet();
        for (auto sw : statement->cases) {
            cstring label;
            if (sw->label->is<IR::DefaultExpression>()) {
                label = "default";
            } else {
                auto pe = sw->label->to<IR::PathExpression>();
                CHECK_NULL(pe);
                label = pe->path->name.name;
            }
            labels->mergeWith(new CFG::EdgeSet(new CFG::Edge(node, label)));
            if (sw->statement != nullptr) {
                current = labels;
                visit(sw->statement);
                labels = new CFG::EdgeSet();
            }  // else we accumulate edges
            if (current != nullptr) {
              result->mergeWith(current);
            }
        }
        setAfter(statement, result);
        return false;
    }

 public:
    CFGBuilder(CFG* cfg, const P4::ReferenceMap* refMap, const P4::TypeMap* typeMap) :
            cfg(cfg), current(nullptr), refMap(refMap), typeMap(typeMap) {}
    const CFG::EdgeSet* run(const IR::Statement* startNode, const CFG::EdgeSet* predecessors) {
        CHECK_NULL(startNode); CHECK_NULL(predecessors);
        current = predecessors;
        LOG1("start " << startNode->node_type_name());
        LOG1("pred " << predecessors);
        startNode->apply(*this);
        return current;
    }
};
}  // end anonymous namespace

void CFG::build(const IR::P4Control* cc,
                const P4::ReferenceMap* refMap, const P4::TypeMap* typeMap) {
    container = cc;
    entryPoint = makeNode("entry");
    exitPoint = makeNode("exit");

    CFGBuilder builder(this, refMap, typeMap);
    auto startValue = new CFG::EdgeSet(new CFG::Edge(entryPoint));
    auto last = builder.run(cc->body, startValue);
    LOG1("Before exit " << last);
    if (last != nullptr) {
        // nullptr can happen when there is an error
        exitPoint->addPredecessors(last);
        computeSuccessors();
    }
}

namespace {
class DiscoverStructure : public Inspector {
    ProgramParts*           structure;

 public:
    explicit DiscoverStructure(ProgramParts* structure) : structure(structure) {}

    void postorder(const IR::ParameterList* paramList) override {
        bool inAction = findContext<IR::P4Action>() != nullptr;
        unsigned index = 0;
        for (auto p : *paramList->getEnumerator()) {
            structure->index.emplace(p, index);
            if (!inAction)
                structure->nonActionParameters.emplace(p);
            index++;
        }
    }
    void postorder(const IR::P4Action* action) override {
        auto control = findContext<IR::P4Control>();
        structure->actions.emplace(action, control);
    }
    void postorder(const IR::Declaration_Variable* decl) override {
        structure->variables.push_back(decl);
    }
};
}  // namespace

void ProgramParts::analyze(IR::ToplevelBlock* toplevel) {
    DiscoverStructure disc(this);
    toplevel->getProgram()->apply(disc);
}

}  // namespace FPGA
<|endoftext|>


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

#include "IncludeInserter.h"

namespace clang {
namespace tidy {

class IncludeInserterCallback : public PPCallbacks {
public:
  explicit IncludeInserterCallback(IncludeInserter *IncludeInserter)
      : IncludeInserter(IncludeInserter) {}
  // Implements PPCallbacks::InclusionDerective(). Records the names and source
  // locations of the inclusions in the main source file being processed.
  void InclusionDirective(SourceLocation HashLocation,
                          const Token & /*include_token*/,
                          StringRef FileNameRef, bool IsAngled,
                          CharSourceRange FileNameRange,
                          const FileEntry * /*IncludedFile*/,
                          StringRef /*SearchPath*/, StringRef /*RelativePath*/,
                          const Module * /*ImportedModule*/) override {
    IncludeInserter->AddInclude(FileNameRef, IsAngled, HashLocation,
                                FileNameRange.getEnd());
  }

private:
  IncludeInserter *IncludeInserter;
};

IncludeInserter::IncludeInserter(const SourceManager &SourceMgr,
                                 const LangOptions &LangOpts,
                                 IncludeSorter::IncludeStyle Style)
    : SourceMgr(SourceMgr), LangOpts(LangOpts), Style(Style) {}

IncludeInserter::~IncludeInserter() {}

std::unique_ptr<PPCallbacks> IncludeInserter::CreatePPCallbacks() {
  return llvm::make_unique<IncludeInserterCallback>(this);
}

llvm::Optional<FixItHint>
IncludeInserter::CreateIncludeInsertion(FileID FileID, StringRef Header,
                                        bool IsAngled) {
  // We assume the same Header will never be included both angled and not
  // angled.
  if (!InsertedHeaders.insert(std::make_pair(FileID, std::set<std::string>()))
           .second) {
    return llvm::None;
  }
  if (IncludeSorterByFile.find(FileID) == IncludeSorterByFile.end()) {
    return llvm::None;
  }
  return IncludeSorterByFile[FileID]->CreateIncludeInsertion(Header, IsAngled);
}

void IncludeInserter::AddInclude(StringRef file_name, bool IsAngled,
                                 SourceLocation HashLocation,
                                 SourceLocation end_location) {
  FileID FileID = SourceMgr.getFileID(HashLocation);
  if (IncludeSorterByFile.find(FileID) == IncludeSorterByFile.end()) {
    IncludeSorterByFile.insert(std::make_pair(
        FileID, llvm::make_unique<IncludeSorter>(
                    &SourceMgr, &LangOpts, FileID,
                    SourceMgr.getFilename(HashLocation), Style)));
  }
  IncludeSorterByFile[FileID]->AddInclude(file_name, IsAngled, HashLocation,
                                          end_location);
}

} // namespace tidy
} // namespace clang
<commit_msg>Fix shadowing of type with variable.<commit_after>//===-------- IncludeInserter.cpp - clang-tidy ----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "IncludeInserter.h"

namespace clang {
namespace tidy {

class IncludeInserterCallback : public PPCallbacks {
public:
  explicit IncludeInserterCallback(IncludeInserter *Inserter)
      : Inserter(Inserter) {}
  // Implements PPCallbacks::InclusionDerective(). Records the names and source
  // locations of the inclusions in the main source file being processed.
  void InclusionDirective(SourceLocation HashLocation,
                          const Token & /*include_token*/,
                          StringRef FileNameRef, bool IsAngled,
                          CharSourceRange FileNameRange,
                          const FileEntry * /*IncludedFile*/,
                          StringRef /*SearchPath*/, StringRef /*RelativePath*/,
                          const Module * /*ImportedModule*/) override {
    Inserter->AddInclude(FileNameRef, IsAngled, HashLocation,
                                FileNameRange.getEnd());
  }

private:
  IncludeInserter *Inserter;
};

IncludeInserter::IncludeInserter(const SourceManager &SourceMgr,
                                 const LangOptions &LangOpts,
                                 IncludeSorter::IncludeStyle Style)
    : SourceMgr(SourceMgr), LangOpts(LangOpts), Style(Style) {}

IncludeInserter::~IncludeInserter() {}

std::unique_ptr<PPCallbacks> IncludeInserter::CreatePPCallbacks() {
  return llvm::make_unique<IncludeInserterCallback>(this);
}

llvm::Optional<FixItHint>
IncludeInserter::CreateIncludeInsertion(FileID FileID, StringRef Header,
                                        bool IsAngled) {
  // We assume the same Header will never be included both angled and not
  // angled.
  if (!InsertedHeaders.insert(std::make_pair(FileID, std::set<std::string>()))
           .second) {
    return llvm::None;
  }
  if (IncludeSorterByFile.find(FileID) == IncludeSorterByFile.end()) {
    return llvm::None;
  }
  return IncludeSorterByFile[FileID]->CreateIncludeInsertion(Header, IsAngled);
}

void IncludeInserter::AddInclude(StringRef file_name, bool IsAngled,
                                 SourceLocation HashLocation,
                                 SourceLocation end_location) {
  FileID FileID = SourceMgr.getFileID(HashLocation);
  if (IncludeSorterByFile.find(FileID) == IncludeSorterByFile.end()) {
    IncludeSorterByFile.insert(std::make_pair(
        FileID, llvm::make_unique<IncludeSorter>(
                    &SourceMgr, &LangOpts, FileID,
                    SourceMgr.getFilename(HashLocation), Style)));
  }
  IncludeSorterByFile[FileID]->AddInclude(file_name, IsAngled, HashLocation,
                                          end_location);
}

} // namespace tidy
} // namespace clang
<|endoftext|>