<commit_before>/*
 * Copyright (c) 2018, 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/rpc_handler_impl.h"

namespace application_manager {
namespace rpc_handler {

CREATE_LOGGERPTR_LOCAL(logger_, "RPCHandlerImpl")
namespace formatters = NsSmartDeviceLink::NsJSONHandler::Formatters;
namespace jhs = NsSmartDeviceLink::NsJSONHandler::strings;

RPCHandlerImpl::RPCHandlerImpl(ApplicationManager& app_manager)
    : app_manager_(app_manager)
    , messages_from_mobile_("AM FromMobile", this)
    , messages_from_hmi_("AM FromHMI", this)
    , hmi_so_factory_(hmi_apis::HMI_API())
    , mobile_so_factory_(mobile_apis::MOBILE_API())
#ifdef TELEMETRY_MONITOR
    , metric_observer_(NULL)
#endif  // TELEMETRY_MONITOR
{
}

RPCHandlerImpl::~RPCHandlerImpl() {}

void RPCHandlerImpl::ProcessMessageFromMobile(
    const utils::SharedPtr<Message> message) {
  LOG4CXX_AUTO_TRACE(logger_);
#ifdef TELEMETRY_MONITOR
  AMTelemetryObserver::MessageMetricSharedPtr metric(
      new AMTelemetryObserver::MessageMetric());
  metric->begin = date_time::DateTime::getCurrentTime();
#endif  // TELEMETRY_MONITOR
  smart_objects::SmartObjectSPtr so_from_mobile =
      utils::MakeShared<smart_objects::SmartObject>();

  DCHECK_OR_RETURN_VOID(so_from_mobile);
  if (!so_from_mobile) {
    LOG4CXX_ERROR(logger_, "Null pointer");
    return;
  }

  if (!ConvertMessageToSO(*message, *so_from_mobile)) {
    LOG4CXX_ERROR(logger_, "Cannot create smart object from message");
    return;
  }
#ifdef TELEMETRY_MONITOR
  metric->message = so_from_mobile;
#endif  // TELEMETRY_MONITOR

  if (!app_manager_.GetRPCService().ManageMobileCommand(
          so_from_mobile, commands::Command::SOURCE_MOBILE)) {
    LOG4CXX_ERROR(logger_, "Received command didn't run successfully");
  }
#ifdef TELEMETRY_MONITOR
  metric->end = date_time::DateTime::getCurrentTime();
  if (metric_observer_) {
    metric_observer_->OnMessage(metric);
  }
#endif  // TELEMETRY_MONITOR
}

void RPCHandlerImpl::ProcessMessageFromHMI(
    const utils::SharedPtr<Message> message) {
  LOG4CXX_AUTO_TRACE(logger_);
  smart_objects::SmartObjectSPtr smart_object(new smart_objects::SmartObject);

  if (!smart_object) {
    LOG4CXX_ERROR(logger_, "Null pointer");
    return;
  }

  if (!ConvertMessageToSO(*message, *smart_object)) {
    if (application_manager::MessageType::kResponse ==
        (*smart_object)[strings::params][strings::message_type].asInt()) {
      (*smart_object).erase(strings::msg_params);
      (*smart_object)[strings::params][hmi_response::code] =
          hmi_apis::Common_Result::GENERIC_ERROR;
      (*smart_object)[strings::msg_params][strings::info] =
          std::string("Invalid message received from vehicle");
    } else {
      LOG4CXX_ERROR(logger_, "Cannot create smart object from message");
      return;
    }
  }

  LOG4CXX_DEBUG(logger_, "Converted message, trying to create hmi command");
  if (!app_manager_.GetRPCService().ManageHMICommand(smart_object)) {
    LOG4CXX_ERROR(logger_, "Received command didn't run successfully");
  }
}
void RPCHandlerImpl::Handle(const impl::MessageFromMobile message) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (!message) {
    LOG4CXX_ERROR(logger_, "Null-pointer message received.");
    return;
  }
  if (app_manager_.is_stopping()) {
    LOG4CXX_INFO(logger_, "Application manager is stopping");
    return;
  }

  ProcessMessageFromMobile(message);
}

void RPCHandlerImpl::Handle(const impl::MessageFromHmi message) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (!message) {
    LOG4CXX_ERROR(logger_, "Null-pointer message received.");
    return;
  }
  ProcessMessageFromHMI(message);
}

void RPCHandlerImpl::OnMessageReceived(
    const protocol_handler::RawMessagePtr message) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (!message) {
    LOG4CXX_ERROR(logger_, "Null-pointer message received.");
    NOTREACHED();
    return;
  }

  utils::SharedPtr<Message> outgoing_message = ConvertRawMsgToMessage(message);

  if (outgoing_message) {
    LOG4CXX_DEBUG(logger_, "Posting new Message");
    messages_from_mobile_.PostMessage(
        impl::MessageFromMobile(outgoing_message));
  }
}

void RPCHandlerImpl::OnMobileMessageSent(
    const protocol_handler::RawMessagePtr message) {
  LOG4CXX_AUTO_TRACE(logger_);
}

void RPCHandlerImpl::OnMessageReceived(
    hmi_message_handler::MessageSharedPointer message) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (!message) {
    LOG4CXX_ERROR(logger_, "Null-pointer message received.");
    NOTREACHED();
    return;
  }

  messages_from_hmi_.PostMessage(impl::MessageFromHmi(message));
}

void RPCHandlerImpl::OnErrorSending(
    hmi_message_handler::MessageSharedPointer message) {
  return;
}

#ifdef TELEMETRY_MONITOR
void RPCHandlerImpl::SetTelemetryObserver(AMTelemetryObserver* observer) {
  metric_observer_ = observer;
}

#endif  // TELEMETRY_MONITOR

bool RPCHandlerImpl::ConvertMessageToSO(
    const Message& message,
    NsSmartDeviceLink::NsSmartObjects::SmartObject& output) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_DEBUG(logger_,
                "\t\t\tMessage to convert: protocol "
                    << message.protocol_version() << "; json "
                    << message.json_message());

  switch (message.protocol_version()) {
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_5:
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_4:
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_3:
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_2: {
      const bool conversion_result =
          formatters::CFormatterJsonSDLRPCv2::fromString(
              message.json_message(),
              output,
              message.function_id(),
              message.type(),
              message.correlation_id());
      if (!conversion_result ||
          !mobile_so_factory().attachSchema(output, true) ||
          ((output.validate() != smart_objects::Errors::OK))) {
        LOG4CXX_WARN(logger_,
                     "Failed to parse string to smart object :"
                         << message.json_message());
        utils::SharedPtr<smart_objects::SmartObject> response(
            MessageHelper::CreateNegativeResponse(
                message.connection_key(),
                message.function_id(),
                message.correlation_id(),
                mobile_apis::Result::INVALID_DATA));
        app_manager_.GetRPCService().ManageMobileCommand(
            response, commands::Command::SOURCE_SDL);
        return false;
      }
      LOG4CXX_DEBUG(logger_,
                    "Convertion result for sdl object is true function_id "
                        << output[jhs::S_PARAMS][jhs::S_FUNCTION_ID].asInt());

      output[strings::params][strings::connection_key] =
          message.connection_key();
      output[strings::params][strings::protocol_version] =
          message.protocol_version();
      if (message.binary_data()) {
        if (message.payload_size() < message.data_size()) {
          LOG4CXX_ERROR(logger_,
                        "Incomplete binary"
                            << " binary size should be  " << message.data_size()
                            << " payload data size is "
                            << message.payload_size());
          utils::SharedPtr<smart_objects::SmartObject> response(
              MessageHelper::CreateNegativeResponse(
                  message.connection_key(),
                  message.function_id(),
                  message.correlation_id(),
                  mobile_apis::Result::INVALID_DATA));
          app_manager_.GetRPCService().ManageMobileCommand(
              response, commands::Command::SOURCE_SDL);
          return false;
        }
        output[strings::params][strings::binary_data] =
            *(message.binary_data());
      }
      break;
    }
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_HMI: {
#ifdef ENABLE_LOG
      int32_t result =
#endif
          formatters::FormatterJsonRpc::FromString<
              hmi_apis::FunctionID::eType,
              hmi_apis::messageType::eType>(message.json_message(), output);
      LOG4CXX_DEBUG(logger_,
                    "Convertion result: "
                        << result << " function id "
                        << output[jhs::S_PARAMS][jhs::S_FUNCTION_ID].asInt());
      if (!hmi_so_factory().attachSchema(output, false)) {
        LOG4CXX_WARN(logger_, "Failed to attach schema to object.");
        return false;
      }
      if (output.validate() != smart_objects::Errors::OK) {
        LOG4CXX_ERROR(logger_, "Incorrect parameter from HMI");
        return false;
      }
      break;
    }
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_1: {
      static NsSmartDeviceLinkRPC::V1::v4_protocol_v1_2_no_extra v1_shema;

      if (message.function_id() == 0 || message.type() == kUnknownType) {
        LOG4CXX_ERROR(logger_, "Message received: UNSUPPORTED_VERSION");

        int32_t conversation_result =
            formatters::CFormatterJsonSDLRPCv1::fromString<
                NsSmartDeviceLinkRPC::V1::FunctionID::eType,
                NsSmartDeviceLinkRPC::V1::messageType::eType>(
                message.json_message(), output);

        if (formatters::CFormatterJsonSDLRPCv1::kSuccess ==
            conversation_result) {
          smart_objects::SmartObject params = smart_objects::SmartObject(
              smart_objects::SmartType::SmartType_Map);

          output[strings::params][strings::message_type] =
              NsSmartDeviceLinkRPC::V1::messageType::response;
          output[strings::params][strings::connection_key] =
              message.connection_key();

          output[strings::msg_params] = smart_objects::SmartObject(
              smart_objects::SmartType::SmartType_Map);
          output[strings::msg_params][strings::success] = false;
          output[strings::msg_params][strings::result_code] =
              NsSmartDeviceLinkRPC::V1::Result::UNSUPPORTED_VERSION;

          smart_objects::SmartObjectSPtr msg_to_send =
              new smart_objects::SmartObject(output);
          v1_shema.attachSchema(*msg_to_send, false);
          app_manager_.GetRPCService().SendMessageToMobile(msg_to_send);
          return false;
        }
      }
      break;
    }
    default:
      LOG4CXX_WARN(logger_,
                   "Application used unsupported protocol :"
                       << message.protocol_version() << ".");
      return false;
  }

  LOG4CXX_DEBUG(logger_, "Successfully parsed message into smart object");
  return true;
}

utils::SharedPtr<Message> RPCHandlerImpl::ConvertRawMsgToMessage(
    const protocol_handler::RawMessagePtr message) {
  LOG4CXX_AUTO_TRACE(logger_);
  DCHECK(message);
  utils::SharedPtr<Message> outgoing_message;

  LOG4CXX_DEBUG(logger_, "Service type." << message->service_type());
  if (message->service_type() != protocol_handler::kRpc &&
      message->service_type() != protocol_handler::kBulk) {
    // skip this message, not under handling of ApplicationManager
    LOG4CXX_TRACE(logger_, "Skipping message; not the under AM handling.");
    return outgoing_message;
  }

  Message* convertion_result =
      MobileMessageHandler::HandleIncomingMessageProtocol(message);

  if (convertion_result) {
    outgoing_message = convertion_result;
  } else {
    LOG4CXX_ERROR(logger_, "Received invalid message");
  }
  return outgoing_message;
}

hmi_apis::HMI_API& RPCHandlerImpl::hmi_so_factory() {
  return hmi_so_factory_;
}

mobile_apis::MOBILE_API& RPCHandlerImpl::mobile_so_factory() {
  return mobile_so_factory_;
}
}
}
<commit_msg>Fix uses of deprecated methods in project<commit_after>/*
 * Copyright (c) 2018, 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/rpc_handler_impl.h"

namespace application_manager {
namespace rpc_handler {

CREATE_LOGGERPTR_LOCAL(logger_, "RPCHandlerImpl")
namespace formatters = NsSmartDeviceLink::NsJSONHandler::Formatters;
namespace jhs = NsSmartDeviceLink::NsJSONHandler::strings;

RPCHandlerImpl::RPCHandlerImpl(ApplicationManager& app_manager)
    : app_manager_(app_manager)
    , messages_from_mobile_("AM FromMobile", this)
    , messages_from_hmi_("AM FromHMI", this)
    , hmi_so_factory_(hmi_apis::HMI_API())
    , mobile_so_factory_(mobile_apis::MOBILE_API())
#ifdef TELEMETRY_MONITOR
    , metric_observer_(NULL)
#endif  // TELEMETRY_MONITOR
{
}

RPCHandlerImpl::~RPCHandlerImpl() {}

void RPCHandlerImpl::ProcessMessageFromMobile(
    const utils::SharedPtr<Message> message) {
  LOG4CXX_AUTO_TRACE(logger_);
#ifdef TELEMETRY_MONITOR
  AMTelemetryObserver::MessageMetricSharedPtr metric(
      new AMTelemetryObserver::MessageMetric());
  metric->begin = date_time::DateTime::getCurrentTime();
#endif  // TELEMETRY_MONITOR
  smart_objects::SmartObjectSPtr so_from_mobile =
      utils::MakeShared<smart_objects::SmartObject>();

  DCHECK_OR_RETURN_VOID(so_from_mobile);
  if (!so_from_mobile) {
    LOG4CXX_ERROR(logger_, "Null pointer");
    return;
  }

  if (!ConvertMessageToSO(*message, *so_from_mobile)) {
    LOG4CXX_ERROR(logger_, "Cannot create smart object from message");
    return;
  }
#ifdef TELEMETRY_MONITOR
  metric->message = so_from_mobile;
#endif  // TELEMETRY_MONITOR

  if (!app_manager_.GetRPCService().ManageMobileCommand(
          so_from_mobile, commands::Command::SOURCE_MOBILE)) {
    LOG4CXX_ERROR(logger_, "Received command didn't run successfully");
  }
#ifdef TELEMETRY_MONITOR
  metric->end = date_time::DateTime::getCurrentTime();
  if (metric_observer_) {
    metric_observer_->OnMessage(metric);
  }
#endif  // TELEMETRY_MONITOR
}

void RPCHandlerImpl::ProcessMessageFromHMI(
    const utils::SharedPtr<Message> message) {
  LOG4CXX_AUTO_TRACE(logger_);
  smart_objects::SmartObjectSPtr smart_object(new smart_objects::SmartObject);

  if (!smart_object) {
    LOG4CXX_ERROR(logger_, "Null pointer");
    return;
  }

  if (!ConvertMessageToSO(*message, *smart_object)) {
    if (application_manager::MessageType::kResponse ==
        (*smart_object)[strings::params][strings::message_type].asInt()) {
      (*smart_object).erase(strings::msg_params);
      (*smart_object)[strings::params][hmi_response::code] =
          hmi_apis::Common_Result::GENERIC_ERROR;
      (*smart_object)[strings::msg_params][strings::info] =
          std::string("Invalid message received from vehicle");
    } else {
      LOG4CXX_ERROR(logger_, "Cannot create smart object from message");
      return;
    }
  }

  LOG4CXX_DEBUG(logger_, "Converted message, trying to create hmi command");
  if (!app_manager_.GetRPCService().ManageHMICommand(smart_object)) {
    LOG4CXX_ERROR(logger_, "Received command didn't run successfully");
  }
}
void RPCHandlerImpl::Handle(const impl::MessageFromMobile message) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (!message) {
    LOG4CXX_ERROR(logger_, "Null-pointer message received.");
    return;
  }
  if (app_manager_.is_stopping()) {
    LOG4CXX_INFO(logger_, "Application manager is stopping");
    return;
  }

  ProcessMessageFromMobile(message);
}

void RPCHandlerImpl::Handle(const impl::MessageFromHmi message) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (!message) {
    LOG4CXX_ERROR(logger_, "Null-pointer message received.");
    return;
  }
  ProcessMessageFromHMI(message);
}

void RPCHandlerImpl::OnMessageReceived(
    const protocol_handler::RawMessagePtr message) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (!message) {
    LOG4CXX_ERROR(logger_, "Null-pointer message received.");
    NOTREACHED();
    return;
  }

  utils::SharedPtr<Message> outgoing_message = ConvertRawMsgToMessage(message);

  if (outgoing_message) {
    LOG4CXX_DEBUG(logger_, "Posting new Message");
    messages_from_mobile_.PostMessage(
        impl::MessageFromMobile(outgoing_message));
  }
}

void RPCHandlerImpl::OnMobileMessageSent(
    const protocol_handler::RawMessagePtr message) {
  LOG4CXX_AUTO_TRACE(logger_);
}

void RPCHandlerImpl::OnMessageReceived(
    hmi_message_handler::MessageSharedPointer message) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (!message) {
    LOG4CXX_ERROR(logger_, "Null-pointer message received.");
    NOTREACHED();
    return;
  }

  messages_from_hmi_.PostMessage(impl::MessageFromHmi(message));
}

void RPCHandlerImpl::OnErrorSending(
    hmi_message_handler::MessageSharedPointer message) {
  return;
}

#ifdef TELEMETRY_MONITOR
void RPCHandlerImpl::SetTelemetryObserver(AMTelemetryObserver* observer) {
  metric_observer_ = observer;
}

#endif  // TELEMETRY_MONITOR

bool RPCHandlerImpl::ConvertMessageToSO(
    const Message& message,
    NsSmartDeviceLink::NsSmartObjects::SmartObject& output) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_DEBUG(logger_,
                "\t\t\tMessage to convert: protocol "
                    << message.protocol_version() << "; json "
                    << message.json_message());

  switch (message.protocol_version()) {
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_5:
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_4:
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_3:
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_2: {
      const bool conversion_result =
          formatters::CFormatterJsonSDLRPCv2::fromString(
              message.json_message(),
              output,
              message.function_id(),
              message.type(),
              message.correlation_id());

      rpc::ValidationReport report("RPC");

      if (!conversion_result ||
          !mobile_so_factory().attachSchema(output, true) ||
          ((output.validate(&report) != smart_objects::Errors::OK))) {
        LOG4CXX_WARN(logger_,
                     "Failed to parse string to smart object :"
                         << message.json_message());
        utils::SharedPtr<smart_objects::SmartObject> response(
            MessageHelper::CreateNegativeResponse(
                message.connection_key(),
                message.function_id(),
                message.correlation_id(),
                mobile_apis::Result::INVALID_DATA));

        (*response)[strings::msg_params][strings::info] =
            rpc::PrettyFormat(report);
        app_manager_.GetRPCService().ManageMobileCommand(
            response, commands::Command::SOURCE_SDL);
        return false;
      }
      LOG4CXX_DEBUG(logger_,
                    "Convertion result for sdl object is true function_id "
                        << output[jhs::S_PARAMS][jhs::S_FUNCTION_ID].asInt());

      output[strings::params][strings::connection_key] =
          message.connection_key();
      output[strings::params][strings::protocol_version] =
          message.protocol_version();
      if (message.binary_data()) {
        if (message.payload_size() < message.data_size()) {
          LOG4CXX_ERROR(logger_,
                        "Incomplete binary"
                            << " binary size should be  " << message.data_size()
                            << " payload data size is "
                            << message.payload_size());
          utils::SharedPtr<smart_objects::SmartObject> response(
              MessageHelper::CreateNegativeResponse(
                  message.connection_key(),
                  message.function_id(),
                  message.correlation_id(),
                  mobile_apis::Result::INVALID_DATA));
          app_manager_.GetRPCService().ManageMobileCommand(
              response, commands::Command::SOURCE_SDL);
          return false;
        }
        output[strings::params][strings::binary_data] =
            *(message.binary_data());
      }
      break;
    }
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_HMI: {
#ifdef ENABLE_LOG
      int32_t result =
#endif
          formatters::FormatterJsonRpc::FromString<
              hmi_apis::FunctionID::eType,
              hmi_apis::messageType::eType>(message.json_message(), output);
      LOG4CXX_DEBUG(logger_,
                    "Convertion result: "
                        << result << " function id "
                        << output[jhs::S_PARAMS][jhs::S_FUNCTION_ID].asInt());
      if (!hmi_so_factory().attachSchema(output, false)) {
        LOG4CXX_WARN(logger_, "Failed to attach schema to object.");
        return false;
      }

      rpc::ValidationReport report("RPC");

      if (output.validate(&report) != smart_objects::Errors::OK) {
        LOG4CXX_ERROR(logger_,
                      "Incorrect parameter from HMI"
                          << rpc::PrettyFormat(report));

        output.erase(strings::msg_params);
        output[strings::params][hmi_response::code] =
            hmi_apis::Common_Result::INVALID_DATA;
        output[strings::msg_params][strings::info] = rpc::PrettyFormat(report);
        return false;
      }
      break;
    }
    case protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_1: {
      static NsSmartDeviceLinkRPC::V1::v4_protocol_v1_2_no_extra v1_shema;

      if (message.function_id() == 0 || message.type() == kUnknownType) {
        LOG4CXX_ERROR(logger_, "Message received: UNSUPPORTED_VERSION");

        int32_t conversation_result =
            formatters::CFormatterJsonSDLRPCv1::fromString<
                NsSmartDeviceLinkRPC::V1::FunctionID::eType,
                NsSmartDeviceLinkRPC::V1::messageType::eType>(
                message.json_message(), output);

        if (formatters::CFormatterJsonSDLRPCv1::kSuccess ==
            conversation_result) {
          smart_objects::SmartObject params = smart_objects::SmartObject(
              smart_objects::SmartType::SmartType_Map);

          output[strings::params][strings::message_type] =
              NsSmartDeviceLinkRPC::V1::messageType::response;
          output[strings::params][strings::connection_key] =
              message.connection_key();

          output[strings::msg_params] = smart_objects::SmartObject(
              smart_objects::SmartType::SmartType_Map);
          output[strings::msg_params][strings::success] = false;
          output[strings::msg_params][strings::result_code] =
              NsSmartDeviceLinkRPC::V1::Result::UNSUPPORTED_VERSION;

          smart_objects::SmartObjectSPtr msg_to_send =
              new smart_objects::SmartObject(output);
          v1_shema.attachSchema(*msg_to_send, false);
          app_manager_.GetRPCService().SendMessageToMobile(msg_to_send);
          return false;
        }
      }
      break;
    }
    default:
      LOG4CXX_WARN(logger_,
                   "Application used unsupported protocol :"
                       << message.protocol_version() << ".");
      return false;
  }

  LOG4CXX_DEBUG(logger_, "Successfully parsed message into smart object");
  return true;
}

utils::SharedPtr<Message> RPCHandlerImpl::ConvertRawMsgToMessage(
    const protocol_handler::RawMessagePtr message) {
  LOG4CXX_AUTO_TRACE(logger_);
  DCHECK(message);
  utils::SharedPtr<Message> outgoing_message;

  LOG4CXX_DEBUG(logger_, "Service type." << message->service_type());
  if (message->service_type() != protocol_handler::kRpc &&
      message->service_type() != protocol_handler::kBulk) {
    // skip this message, not under handling of ApplicationManager
    LOG4CXX_TRACE(logger_, "Skipping message; not the under AM handling.");
    return outgoing_message;
  }

  Message* convertion_result =
      MobileMessageHandler::HandleIncomingMessageProtocol(message);

  if (convertion_result) {
    outgoing_message = convertion_result;
  } else {
    LOG4CXX_ERROR(logger_, "Received invalid message");
  }
  return outgoing_message;
}

hmi_apis::HMI_API& RPCHandlerImpl::hmi_so_factory() {
  return hmi_so_factory_;
}

mobile_apis::MOBILE_API& RPCHandlerImpl::mobile_so_factory() {
  return mobile_so_factory_;
}
}
}
<|endoftext|>


<commit_before>#include "inverseIndexStorageBloomierFilter.h"

InverseIndexStorageBloomierFilter::InverseIndexStorageBloomierFilter(size_t pSizeOfInverseIndex, size_t pMaxBinSize) {
	mInverseIndex = new std::vector<BloomierFilter* > (pSizeOfInverseIndex);
	mMaxBinSize = pMaxBinSize;
	mKeys = new vvsize_t(pSizeOfInverseIndex, vsize_t());
	mValues = new vvsize_t(pSizeOfInverseIndex, vsize_t());
	mM = 100;
	mK = 100;
	mQ = 100;

}
InverseIndexStorageBloomierFilter::~InverseIndexStorageBloomierFilter() {

}
size_t InverseIndexStorageBloomierFilter::size() {
	return mInverseIndex->size();
}
vsize_t* InverseIndexStorageBloomierFilter::getElement(size_t pVectorId, size_t pHashValue) {
    return (*mInverseIndex)[pVectorId]->get(pHashValue);
}
void InverseIndexStorageBloomierFilter::insert(size_t pVectorId, size_t pHashValue, size_t pInstance) {
	if ((*mInverseIndex)[pVectorId] == NULL) {
		(*mInverseIndex)[pVectorId] = new BloomierFilter(mM, mK, mQ);
	}
	(*mInverseIndex)[pVectorId]->set(pHashValue, pInstance);
}<commit_msg>Commented unused variables out<commit_after>#include "inverseIndexStorageBloomierFilter.h"

InverseIndexStorageBloomierFilter::InverseIndexStorageBloomierFilter(size_t pSizeOfInverseIndex, size_t pMaxBinSize) {
	mInverseIndex = new std::vector<BloomierFilter* > (pSizeOfInverseIndex);
	// mMaxBinSize = pMaxBinSize;
	// mKeys = new vvsize_t(pSizeOfInverseIndex, vsize_t());
	// mValues = new vvsize_t(pSizeOfInverseIndex, vsize_t());
	mM = 10;
	mK = 3;
	mQ = 13;

}
InverseIndexStorageBloomierFilter::~InverseIndexStorageBloomierFilter() {

}
size_t InverseIndexStorageBloomierFilter::size() {
	return mInverseIndex->size();
}
vsize_t* InverseIndexStorageBloomierFilter::getElement(size_t pVectorId, size_t pHashValue) {
    return (*mInverseIndex)[pVectorId]->get(pHashValue);
}
void InverseIndexStorageBloomierFilter::insert(size_t pVectorId, size_t pHashValue, size_t pInstance) {
	if ((*mInverseIndex)[pVectorId] == NULL) {
		(*mInverseIndex)[pVectorId] = new BloomierFilter(mM, mK, mQ);
	}
	(*mInverseIndex)[pVectorId]->set(pHashValue, pInstance);
}<|endoftext|>


<commit_before>//===--------------- PPCVSXFMAMutate.cpp - VSX FMA Mutation ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass mutates the form of VSX FMA instructions to avoid unnecessary
// copies.
//
//===----------------------------------------------------------------------===//

#include "PPCInstrInfo.h"
#include "MCTargetDesc/PPCPredicates.h"
#include "PPC.h"
#include "PPCInstrBuilder.h"
#include "PPCMachineFunctionInfo.h"
#include "PPCTargetMachine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<bool> DisableVSXFMAMutate("disable-ppc-vsx-fma-mutation",
cl::desc("Disable VSX FMA instruction mutation"), cl::Hidden);

#define DEBUG_TYPE "ppc-vsx-fma-mutate"

namespace llvm { namespace PPC {
  int getAltVSXFMAOpcode(uint16_t Opcode);
} }

namespace {
  // PPCVSXFMAMutate pass - For copies between VSX registers and non-VSX registers
  // (Altivec and scalar floating-point registers), we need to transform the
  // copies into subregister copies with other restrictions.
  struct PPCVSXFMAMutate : public MachineFunctionPass {
    static char ID;
    PPCVSXFMAMutate() : MachineFunctionPass(ID) {
      initializePPCVSXFMAMutatePass(*PassRegistry::getPassRegistry());
    }

    LiveIntervals *LIS;
    const PPCInstrInfo *TII;

protected:
    bool processBlock(MachineBasicBlock &MBB) {
      bool Changed = false;

      MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
      const TargetRegisterInfo *TRI = &TII->getRegisterInfo();
      for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end();
           I != IE; ++I) {
        MachineInstr *MI = I;

        // The default (A-type) VSX FMA form kills the addend (it is taken from
        // the target register, which is then updated to reflect the result of
        // the FMA). If the instruction, however, kills one of the registers
        // used for the product, then we can use the M-form instruction (which
        // will take that value from the to-be-defined register).

        int AltOpc = PPC::getAltVSXFMAOpcode(MI->getOpcode());
        if (AltOpc == -1)
          continue;

        // This pass is run after register coalescing, and so we're looking for
        // a situation like this:
        //   ...
        //   %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
        //   %vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
        //                         %RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
        //   ...
        //   %vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
        //                         %RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
        //   ...
        // Where we can eliminate the copy by changing from the A-type to the
        // M-type instruction. Specifically, for this example, this means:
        //   %vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
        //                         %RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
        // is replaced by:
        //   %vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
        //                         %RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
        // and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9

        SlotIndex FMAIdx = LIS->getInstructionIndex(MI);

        VNInfo *AddendValNo =
          LIS->getInterval(MI->getOperand(1).getReg()).Query(FMAIdx).valueIn();
        MachineInstr *AddendMI = LIS->getInstructionFromIndex(AddendValNo->def);

        // The addend and this instruction must be in the same block.

        if (!AddendMI || AddendMI->getParent() != MI->getParent())
          continue;

        // The addend must be a full copy within the same register class.

        if (!AddendMI->isFullCopy())
          continue;

        unsigned AddendSrcReg = AddendMI->getOperand(1).getReg();
        if (TargetRegisterInfo::isVirtualRegister(AddendSrcReg)) {
          if (MRI.getRegClass(AddendMI->getOperand(0).getReg()) !=
              MRI.getRegClass(AddendSrcReg))
            continue;
        } else {
          // If AddendSrcReg is a physical register, make sure the destination
          // register class contains it.
          if (!MRI.getRegClass(AddendMI->getOperand(0).getReg())
                ->contains(AddendSrcReg))
            continue;
        }

        // In theory, there could be other uses of the addend copy before this
        // fma.  We could deal with this, but that would require additional
        // logic below and I suspect it will not occur in any relevant
        // situations.  Additionally, check whether the copy source is killed
        // prior to the fma.  In order to replace the addend here with the
        // source of the copy, it must still be live here.  We can't use
        // interval testing for a physical register, so as long as we're
        // walking the MIs we may as well test liveness here.
        bool OtherUsers = false, KillsAddendSrc = false;
        for (auto J = std::prev(I), JE = MachineBasicBlock::iterator(AddendMI);
             J != JE; --J) {
          if (J->readsVirtualRegister(AddendMI->getOperand(0).getReg())) {
            OtherUsers = true;
            break;
          }
          if (J->modifiesRegister(AddendSrcReg, TRI) ||
              J->killsRegister(AddendSrcReg, TRI)) {
            KillsAddendSrc = true;
            break;
          }
        }

        if (OtherUsers || KillsAddendSrc)
          continue;

        // Find one of the product operands that is killed by this instruction.

        unsigned KilledProdOp = 0, OtherProdOp = 0;
        if (LIS->getInterval(MI->getOperand(2).getReg())
                     .Query(FMAIdx).isKill()) {
          KilledProdOp = 2;
          OtherProdOp  = 3;
        } else if (LIS->getInterval(MI->getOperand(3).getReg())
                     .Query(FMAIdx).isKill()) {
          KilledProdOp = 3;
          OtherProdOp  = 2;
        }

        // If there are no killed product operands, then this transformation is
        // likely not profitable.
        if (!KilledProdOp)
          continue;

        // For virtual registers, verify that the addend source register
        // is live here (as should have been assured above).
        assert((!TargetRegisterInfo::isVirtualRegister(AddendSrcReg) ||
                LIS->getInterval(AddendSrcReg).liveAt(FMAIdx)) &&
               "Addend source register is not live!");

        // Transform: (O2 * O3) + O1 -> (O2 * O1) + O3.

        unsigned AddReg = AddendMI->getOperand(1).getReg();
        unsigned KilledProdReg = MI->getOperand(KilledProdOp).getReg();
        unsigned OtherProdReg  = MI->getOperand(OtherProdOp).getReg();

        unsigned AddSubReg = AddendMI->getOperand(1).getSubReg();
        unsigned KilledProdSubReg = MI->getOperand(KilledProdOp).getSubReg();
        unsigned OtherProdSubReg  = MI->getOperand(OtherProdOp).getSubReg();

        bool AddRegKill = AddendMI->getOperand(1).isKill();
        bool KilledProdRegKill = MI->getOperand(KilledProdOp).isKill();
        bool OtherProdRegKill  = MI->getOperand(OtherProdOp).isKill();

        bool AddRegUndef = AddendMI->getOperand(1).isUndef();
        bool KilledProdRegUndef = MI->getOperand(KilledProdOp).isUndef();
        bool OtherProdRegUndef  = MI->getOperand(OtherProdOp).isUndef();

        unsigned OldFMAReg = MI->getOperand(0).getReg();

        // The transformation doesn't work well with things like:
        //    %vreg5 = A-form-op %vreg5, %vreg11, %vreg5;
        // so leave such things alone.
        if (OldFMAReg == KilledProdReg)
          continue;

        assert(OldFMAReg == AddendMI->getOperand(0).getReg() &&
               "Addend copy not tied to old FMA output!");

        DEBUG(dbgs() << "VSX FMA Mutation:\n    " << *MI;);

        MI->getOperand(0).setReg(KilledProdReg);
        MI->getOperand(1).setReg(KilledProdReg);
        MI->getOperand(3).setReg(AddReg);
        MI->getOperand(2).setReg(OtherProdReg);

        MI->getOperand(0).setSubReg(KilledProdSubReg);
        MI->getOperand(1).setSubReg(KilledProdSubReg);
        MI->getOperand(3).setSubReg(AddSubReg);
        MI->getOperand(2).setSubReg(OtherProdSubReg);

        MI->getOperand(1).setIsKill(KilledProdRegKill);
        MI->getOperand(3).setIsKill(AddRegKill);
        MI->getOperand(2).setIsKill(OtherProdRegKill);

        MI->getOperand(1).setIsUndef(KilledProdRegUndef);
        MI->getOperand(3).setIsUndef(AddRegUndef);
        MI->getOperand(2).setIsUndef(OtherProdRegUndef);

        MI->setDesc(TII->get(AltOpc));

        DEBUG(dbgs() << " -> " << *MI);

        // The killed product operand was killed here, so we can reuse it now
        // for the result of the fma.

        LiveInterval &FMAInt = LIS->getInterval(OldFMAReg);
        VNInfo *FMAValNo = FMAInt.getVNInfoAt(FMAIdx.getRegSlot());
        for (auto UI = MRI.reg_nodbg_begin(OldFMAReg), UE = MRI.reg_nodbg_end();
             UI != UE;) {
          MachineOperand &UseMO = *UI;
          MachineInstr *UseMI = UseMO.getParent();
          ++UI;

          // Don't replace the result register of the copy we're about to erase.
          if (UseMI == AddendMI)
            continue;

          UseMO.setReg(KilledProdReg);
          UseMO.setSubReg(KilledProdSubReg);
        }

        // Extend the live intervals of the killed product operand to hold the
        // fma result.

        LiveInterval &NewFMAInt = LIS->getInterval(KilledProdReg);
        for (LiveInterval::iterator AI = FMAInt.begin(), AE = FMAInt.end();
             AI != AE; ++AI) {
          // Don't add the segment that corresponds to the original copy.
          if (AI->valno == AddendValNo)
            continue;

          VNInfo *NewFMAValNo =
            NewFMAInt.getNextValue(AI->start,
                                   LIS->getVNInfoAllocator());

          NewFMAInt.addSegment(LiveInterval::Segment(AI->start, AI->end,
                                                     NewFMAValNo));
        }
        DEBUG(dbgs() << "  extended: " << NewFMAInt << '\n');

        FMAInt.removeValNo(FMAValNo);
        DEBUG(dbgs() << "  trimmed:  " << FMAInt << '\n');

        // Remove the (now unused) copy.

        DEBUG(dbgs() << "  removing: " << *AddendMI << '\n');
        LIS->RemoveMachineInstrFromMaps(AddendMI);
        AddendMI->eraseFromParent();

        Changed = true;
      }

      return Changed;
    }

public:
    bool runOnMachineFunction(MachineFunction &MF) override {
      // If we don't have VSX then go ahead and return without doing
      // anything.
      const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();
      if (!STI.hasVSX())
        return false;

      LIS = &getAnalysis<LiveIntervals>();

      TII = STI.getInstrInfo();

      bool Changed = false;

      if (DisableVSXFMAMutate)
        return Changed;

      for (MachineFunction::iterator I = MF.begin(); I != MF.end();) {
        MachineBasicBlock &B = *I++;
        if (processBlock(B))
          Changed = true;
      }

      return Changed;
    }

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.addRequired<LiveIntervals>();
      AU.addPreserved<LiveIntervals>();
      AU.addRequired<SlotIndexes>();
      AU.addPreserved<SlotIndexes>();
      MachineFunctionPass::getAnalysisUsage(AU);
    }
  };
}

INITIALIZE_PASS_BEGIN(PPCVSXFMAMutate, DEBUG_TYPE,
                      "PowerPC VSX FMA Mutation", false, false)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
INITIALIZE_PASS_END(PPCVSXFMAMutate, DEBUG_TYPE,
                    "PowerPC VSX FMA Mutation", false, false)

char &llvm::PPCVSXFMAMutateID = PPCVSXFMAMutate::ID;

char PPCVSXFMAMutate::ID = 0;
FunctionPass*
llvm::createPPCVSXFMAMutatePass() { return new PPCVSXFMAMutate(); }

<commit_msg>[PowerPC] Remove unnecessary include<commit_after>//===--------------- PPCVSXFMAMutate.cpp - VSX FMA Mutation ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass mutates the form of VSX FMA instructions to avoid unnecessary
// copies.
//
//===----------------------------------------------------------------------===//

#include "PPCInstrInfo.h"
#include "MCTargetDesc/PPCPredicates.h"
#include "PPC.h"
#include "PPCInstrBuilder.h"
#include "PPCMachineFunctionInfo.h"
#include "PPCTargetMachine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<bool> DisableVSXFMAMutate("disable-ppc-vsx-fma-mutation",
cl::desc("Disable VSX FMA instruction mutation"), cl::Hidden);

#define DEBUG_TYPE "ppc-vsx-fma-mutate"

namespace llvm { namespace PPC {
  int getAltVSXFMAOpcode(uint16_t Opcode);
} }

namespace {
  // PPCVSXFMAMutate pass - For copies between VSX registers and non-VSX registers
  // (Altivec and scalar floating-point registers), we need to transform the
  // copies into subregister copies with other restrictions.
  struct PPCVSXFMAMutate : public MachineFunctionPass {
    static char ID;
    PPCVSXFMAMutate() : MachineFunctionPass(ID) {
      initializePPCVSXFMAMutatePass(*PassRegistry::getPassRegistry());
    }

    LiveIntervals *LIS;
    const PPCInstrInfo *TII;

protected:
    bool processBlock(MachineBasicBlock &MBB) {
      bool Changed = false;

      MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
      const TargetRegisterInfo *TRI = &TII->getRegisterInfo();
      for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end();
           I != IE; ++I) {
        MachineInstr *MI = I;

        // The default (A-type) VSX FMA form kills the addend (it is taken from
        // the target register, which is then updated to reflect the result of
        // the FMA). If the instruction, however, kills one of the registers
        // used for the product, then we can use the M-form instruction (which
        // will take that value from the to-be-defined register).

        int AltOpc = PPC::getAltVSXFMAOpcode(MI->getOpcode());
        if (AltOpc == -1)
          continue;

        // This pass is run after register coalescing, and so we're looking for
        // a situation like this:
        //   ...
        //   %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
        //   %vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
        //                         %RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
        //   ...
        //   %vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
        //                         %RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
        //   ...
        // Where we can eliminate the copy by changing from the A-type to the
        // M-type instruction. Specifically, for this example, this means:
        //   %vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
        //                         %RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
        // is replaced by:
        //   %vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
        //                         %RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
        // and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9

        SlotIndex FMAIdx = LIS->getInstructionIndex(MI);

        VNInfo *AddendValNo =
          LIS->getInterval(MI->getOperand(1).getReg()).Query(FMAIdx).valueIn();
        MachineInstr *AddendMI = LIS->getInstructionFromIndex(AddendValNo->def);

        // The addend and this instruction must be in the same block.

        if (!AddendMI || AddendMI->getParent() != MI->getParent())
          continue;

        // The addend must be a full copy within the same register class.

        if (!AddendMI->isFullCopy())
          continue;

        unsigned AddendSrcReg = AddendMI->getOperand(1).getReg();
        if (TargetRegisterInfo::isVirtualRegister(AddendSrcReg)) {
          if (MRI.getRegClass(AddendMI->getOperand(0).getReg()) !=
              MRI.getRegClass(AddendSrcReg))
            continue;
        } else {
          // If AddendSrcReg is a physical register, make sure the destination
          // register class contains it.
          if (!MRI.getRegClass(AddendMI->getOperand(0).getReg())
                ->contains(AddendSrcReg))
            continue;
        }

        // In theory, there could be other uses of the addend copy before this
        // fma.  We could deal with this, but that would require additional
        // logic below and I suspect it will not occur in any relevant
        // situations.  Additionally, check whether the copy source is killed
        // prior to the fma.  In order to replace the addend here with the
        // source of the copy, it must still be live here.  We can't use
        // interval testing for a physical register, so as long as we're
        // walking the MIs we may as well test liveness here.
        bool OtherUsers = false, KillsAddendSrc = false;
        for (auto J = std::prev(I), JE = MachineBasicBlock::iterator(AddendMI);
             J != JE; --J) {
          if (J->readsVirtualRegister(AddendMI->getOperand(0).getReg())) {
            OtherUsers = true;
            break;
          }
          if (J->modifiesRegister(AddendSrcReg, TRI) ||
              J->killsRegister(AddendSrcReg, TRI)) {
            KillsAddendSrc = true;
            break;
          }
        }

        if (OtherUsers || KillsAddendSrc)
          continue;

        // Find one of the product operands that is killed by this instruction.

        unsigned KilledProdOp = 0, OtherProdOp = 0;
        if (LIS->getInterval(MI->getOperand(2).getReg())
                     .Query(FMAIdx).isKill()) {
          KilledProdOp = 2;
          OtherProdOp  = 3;
        } else if (LIS->getInterval(MI->getOperand(3).getReg())
                     .Query(FMAIdx).isKill()) {
          KilledProdOp = 3;
          OtherProdOp  = 2;
        }

        // If there are no killed product operands, then this transformation is
        // likely not profitable.
        if (!KilledProdOp)
          continue;

        // For virtual registers, verify that the addend source register
        // is live here (as should have been assured above).
        assert((!TargetRegisterInfo::isVirtualRegister(AddendSrcReg) ||
                LIS->getInterval(AddendSrcReg).liveAt(FMAIdx)) &&
               "Addend source register is not live!");

        // Transform: (O2 * O3) + O1 -> (O2 * O1) + O3.

        unsigned AddReg = AddendMI->getOperand(1).getReg();
        unsigned KilledProdReg = MI->getOperand(KilledProdOp).getReg();
        unsigned OtherProdReg  = MI->getOperand(OtherProdOp).getReg();

        unsigned AddSubReg = AddendMI->getOperand(1).getSubReg();
        unsigned KilledProdSubReg = MI->getOperand(KilledProdOp).getSubReg();
        unsigned OtherProdSubReg  = MI->getOperand(OtherProdOp).getSubReg();

        bool AddRegKill = AddendMI->getOperand(1).isKill();
        bool KilledProdRegKill = MI->getOperand(KilledProdOp).isKill();
        bool OtherProdRegKill  = MI->getOperand(OtherProdOp).isKill();

        bool AddRegUndef = AddendMI->getOperand(1).isUndef();
        bool KilledProdRegUndef = MI->getOperand(KilledProdOp).isUndef();
        bool OtherProdRegUndef  = MI->getOperand(OtherProdOp).isUndef();

        unsigned OldFMAReg = MI->getOperand(0).getReg();

        // The transformation doesn't work well with things like:
        //    %vreg5 = A-form-op %vreg5, %vreg11, %vreg5;
        // so leave such things alone.
        if (OldFMAReg == KilledProdReg)
          continue;

        assert(OldFMAReg == AddendMI->getOperand(0).getReg() &&
               "Addend copy not tied to old FMA output!");

        DEBUG(dbgs() << "VSX FMA Mutation:\n    " << *MI;);

        MI->getOperand(0).setReg(KilledProdReg);
        MI->getOperand(1).setReg(KilledProdReg);
        MI->getOperand(3).setReg(AddReg);
        MI->getOperand(2).setReg(OtherProdReg);

        MI->getOperand(0).setSubReg(KilledProdSubReg);
        MI->getOperand(1).setSubReg(KilledProdSubReg);
        MI->getOperand(3).setSubReg(AddSubReg);
        MI->getOperand(2).setSubReg(OtherProdSubReg);

        MI->getOperand(1).setIsKill(KilledProdRegKill);
        MI->getOperand(3).setIsKill(AddRegKill);
        MI->getOperand(2).setIsKill(OtherProdRegKill);

        MI->getOperand(1).setIsUndef(KilledProdRegUndef);
        MI->getOperand(3).setIsUndef(AddRegUndef);
        MI->getOperand(2).setIsUndef(OtherProdRegUndef);

        MI->setDesc(TII->get(AltOpc));

        DEBUG(dbgs() << " -> " << *MI);

        // The killed product operand was killed here, so we can reuse it now
        // for the result of the fma.

        LiveInterval &FMAInt = LIS->getInterval(OldFMAReg);
        VNInfo *FMAValNo = FMAInt.getVNInfoAt(FMAIdx.getRegSlot());
        for (auto UI = MRI.reg_nodbg_begin(OldFMAReg), UE = MRI.reg_nodbg_end();
             UI != UE;) {
          MachineOperand &UseMO = *UI;
          MachineInstr *UseMI = UseMO.getParent();
          ++UI;

          // Don't replace the result register of the copy we're about to erase.
          if (UseMI == AddendMI)
            continue;

          UseMO.setReg(KilledProdReg);
          UseMO.setSubReg(KilledProdSubReg);
        }

        // Extend the live intervals of the killed product operand to hold the
        // fma result.

        LiveInterval &NewFMAInt = LIS->getInterval(KilledProdReg);
        for (LiveInterval::iterator AI = FMAInt.begin(), AE = FMAInt.end();
             AI != AE; ++AI) {
          // Don't add the segment that corresponds to the original copy.
          if (AI->valno == AddendValNo)
            continue;

          VNInfo *NewFMAValNo =
            NewFMAInt.getNextValue(AI->start,
                                   LIS->getVNInfoAllocator());

          NewFMAInt.addSegment(LiveInterval::Segment(AI->start, AI->end,
                                                     NewFMAValNo));
        }
        DEBUG(dbgs() << "  extended: " << NewFMAInt << '\n');

        FMAInt.removeValNo(FMAValNo);
        DEBUG(dbgs() << "  trimmed:  " << FMAInt << '\n');

        // Remove the (now unused) copy.

        DEBUG(dbgs() << "  removing: " << *AddendMI << '\n');
        LIS->RemoveMachineInstrFromMaps(AddendMI);
        AddendMI->eraseFromParent();

        Changed = true;
      }

      return Changed;
    }

public:
    bool runOnMachineFunction(MachineFunction &MF) override {
      // If we don't have VSX then go ahead and return without doing
      // anything.
      const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();
      if (!STI.hasVSX())
        return false;

      LIS = &getAnalysis<LiveIntervals>();

      TII = STI.getInstrInfo();

      bool Changed = false;

      if (DisableVSXFMAMutate)
        return Changed;

      for (MachineFunction::iterator I = MF.begin(); I != MF.end();) {
        MachineBasicBlock &B = *I++;
        if (processBlock(B))
          Changed = true;
      }

      return Changed;
    }

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.addRequired<LiveIntervals>();
      AU.addPreserved<LiveIntervals>();
      AU.addRequired<SlotIndexes>();
      AU.addPreserved<SlotIndexes>();
      MachineFunctionPass::getAnalysisUsage(AU);
    }
  };
}

INITIALIZE_PASS_BEGIN(PPCVSXFMAMutate, DEBUG_TYPE,
                      "PowerPC VSX FMA Mutation", false, false)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
INITIALIZE_PASS_END(PPCVSXFMAMutate, DEBUG_TYPE,
                    "PowerPC VSX FMA Mutation", false, false)

char &llvm::PPCVSXFMAMutateID = PPCVSXFMAMutate::ID;

char PPCVSXFMAMutate::ID = 0;
FunctionPass*
llvm::createPPCVSXFMAMutatePass() { return new PPCVSXFMAMutate(); }

<|endoftext|>


<commit_before>#include "catch.hpp"

#include <array>
#include <oroch/varint.h>

using varint32 = oroch::varint_codec<uint32_t>;
using varint64 = oroch::varint_codec<uint64_t>;

TEST_CASE("varint codec for single value", "[varint]") {

	std::array<uint8_t, 10> bytes;

	auto it = bytes.begin();
	varint32::value_encode(it, 1);
	REQUIRE(it == bytes.begin() + 1);
	REQUIRE(bytes[0] == 1);

	it = bytes.begin();
	varint32::value_encode(it, 2);
	REQUIRE(it == bytes.begin() + 1);
	REQUIRE(bytes[0] == 2);

	it = bytes.begin();
	varint32::value_encode(it, 127);
	REQUIRE(it == bytes.begin() + 1);
	REQUIRE(bytes[0] == 127);

	it = bytes.begin();
	varint32::value_encode(it, 128);
	REQUIRE(it == bytes.begin() + 2);
	REQUIRE(bytes[0] == 128);
	REQUIRE(bytes[1] == 1);

	for (uint32_t i = 1; i != 0; i += i) {
		oroch::dst_bytes_t d_it = bytes.begin();
		varint32::value_encode(d_it, i);

		uint32_t j;
		oroch::src_bytes_t b_it = bytes.begin();
		varint32::value_decode(j, b_it);
		REQUIRE(i == j);
	}

	for (uint64_t i = 1; i != 0; i += i) {
		oroch::dst_bytes_t d_it = bytes.begin();
		varint64::value_encode(d_it, i);

		uint64_t j;
		oroch::src_bytes_t b_it = bytes.begin();
		varint64::value_decode(j, b_it);
		REQUIRE(i == j);
	}
}

TEST_CASE("varint codec for array", "[varint]") {
	std::array<uint8_t, 15> bytes;
	std::array<uint32_t, 5> integers {{
		0, 0x80, 0x4000, 0x200000, 0x1000000
	}};

	oroch::dst_bytes_t d_it = bytes.begin();
	auto i_it = integers.begin();
	varint32::encode(d_it, i_it, integers.end());

	std::array<uint32_t, 5> integers2;
	oroch::src_bytes_t b_it = bytes.begin();
	i_it = integers2.begin();
	varint32::decode(i_it, integers2.end(), b_it);

	for (size_t i = 0; i < integers.size(); i++) {
		REQUIRE(integers[i] == integers2[i]);
	}
}
<commit_msg>Add varint value space unit test<commit_after>#include "catch.hpp"

#include <array>
#include <oroch/varint.h>

using varint32 = oroch::varint_codec<uint32_t>;
using varint64 = oroch::varint_codec<uint64_t>;

TEST_CASE("varint codec space calculation", "[varint]") {
	REQUIRE(varint64::value_space(0) == 1);
	REQUIRE(varint64::value_space(1) == 1);
	REQUIRE(varint64::value_space(127) == 1);
	REQUIRE(varint64::value_space(128) == 2);
	REQUIRE(varint64::value_space(16383) == 2);
	REQUIRE(varint64::value_space(16384) == 3);
	REQUIRE(varint64::value_space(UINT64_MAX) == 10);
}

TEST_CASE("varint codec for single value", "[varint]") {

	std::array<uint8_t, 10> bytes;

	auto it = bytes.begin();
	varint32::value_encode(it, 1);
	REQUIRE(it == bytes.begin() + 1);
	REQUIRE(bytes[0] == 1);

	it = bytes.begin();
	varint32::value_encode(it, 2);
	REQUIRE(it == bytes.begin() + 1);
	REQUIRE(bytes[0] == 2);

	it = bytes.begin();
	varint32::value_encode(it, 127);
	REQUIRE(it == bytes.begin() + 1);
	REQUIRE(bytes[0] == 127);

	it = bytes.begin();
	varint32::value_encode(it, 128);
	REQUIRE(it == bytes.begin() + 2);
	REQUIRE(bytes[0] == 128);
	REQUIRE(bytes[1] == 1);

	for (uint32_t i = 1; i != 0; i += i) {
		oroch::dst_bytes_t d_it = bytes.begin();
		varint32::value_encode(d_it, i);

		uint32_t j;
		oroch::src_bytes_t b_it = bytes.begin();
		varint32::value_decode(j, b_it);
		REQUIRE(i == j);
	}

	for (uint64_t i = 1; i != 0; i += i) {
		oroch::dst_bytes_t d_it = bytes.begin();
		varint64::value_encode(d_it, i);

		uint64_t j;
		oroch::src_bytes_t b_it = bytes.begin();
		varint64::value_decode(j, b_it);
		REQUIRE(i == j);
	}
}

TEST_CASE("varint codec for array", "[varint]") {
	std::array<uint8_t, 15> bytes;
	std::array<uint32_t, 5> integers {{
		0, 0x80, 0x4000, 0x200000, 0x1000000
	}};

	oroch::dst_bytes_t d_it = bytes.begin();
	auto i_it = integers.begin();
	varint32::encode(d_it, i_it, integers.end());

	std::array<uint32_t, 5> integers2;
	oroch::src_bytes_t b_it = bytes.begin();
	i_it = integers2.begin();
	varint32::decode(i_it, integers2.end(), b_it);

	for (size_t i = 0; i < integers.size(); i++) {
		REQUIRE(integers[i] == integers2[i]);
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: office_connect.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2003-06-30 15:43:45 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  the BSD license.
 *
 *  Copyright (c) 2003 by Sun Microsystems, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. 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.
 *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *************************************************************************/

#include <stdio.h>

#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/bridge/XUnoUrlResolver.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>

using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::bridge;
using namespace rtl;
using namespace cppu;

int main( )
{
    // create the initial component context
    Reference< XComponentContext > rComponentContext =
        defaultBootstrap_InitialComponentContext();

    // retrieve the servicemanager from the context
    Reference< XMultiComponentFactory > rServiceManager =
        rComponentContext->getServiceManager();

    // instantiate a sample service with the servicemanager.
    Reference< XInterface > rInstance =
        rServiceManager->createInstanceWithContext(
            OUString::createFromAscii("com.sun.star.bridge.UnoUrlResolver" ),
            rComponentContext );

    // Query for the XUnoUrlResolver interface
    Reference< XUnoUrlResolver > rResolver( rInstance, UNO_QUERY );

    if( ! rResolver.is() )
    {
        printf( "Error: Couldn't instantiate com.sun.star.bridge.UnoUrlResolver service\n" );
        return 1;
    }
    try
    {
        // resolve the uno-url
        rInstance = rResolver->resolve( OUString::createFromAscii(
            "uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" ) );

        if( ! rInstance.is() )
        {
            printf( "StarOffice.ServiceManager is not exported from remote counterpart\n" );
            return 1;
        }

        // query for the simpler XMultiServiceFactory interface, sufficient for scripting
        Reference< XMultiServiceFactory > rOfficeServiceManager (rInstance, UNO_QUERY);

        if( ! rInstance.is() )
        {
            printf( "XMultiServiceFactory interface is not exported for StarOffice.ServiceManager\n" );
            return 1;
        }

        printf( "Connected sucessfully to the office\n" );
    }
    catch( Exception &e )
    {
        OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
        printf( "Error: %s\n", o.pData->buffer );
        return 1;
    }
    return 0;
}
<commit_msg>INTEGRATION: CWS geordi2q14 (1.3.72); FILE MERGED 2004/01/30 13:11:35 hr 1.3.72.1: #111934#: merge CWS ooo111fix2<commit_after>/*************************************************************************
 *
 *  $RCSfile: office_connect.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2004-02-02 20:02:57 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  the BSD license.
 *
 *  Copyright (c) 2003 by Sun Microsystems, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. 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.
 *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *************************************************************************/

#include <stdio.h>

#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/bridge/XUnoUrlResolver.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>

using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::bridge;
using namespace rtl;
using namespace cppu;

int main( )
{
    // create the initial component context
    Reference< XComponentContext > rComponentContext =
        defaultBootstrap_InitialComponentContext();

    // retrieve the servicemanager from the context
    Reference< XMultiComponentFactory > rServiceManager =
        rComponentContext->getServiceManager();

    // instantiate a sample service with the servicemanager.
    Reference< XInterface > rInstance =
        rServiceManager->createInstanceWithContext(
            OUString::createFromAscii("com.sun.star.bridge.UnoUrlResolver" ),
            rComponentContext );

    // Query for the XUnoUrlResolver interface
    Reference< XUnoUrlResolver > rResolver( rInstance, UNO_QUERY );

    if( ! rResolver.is() )
    {
        printf( "Error: Couldn't instantiate com.sun.star.bridge.UnoUrlResolver service\n" );
        return 1;
    }
    try
    {
        // resolve the uno-url
        rInstance = rResolver->resolve( OUString::createFromAscii(
            "uno:socket,host=localhost,port=2083;urp;StarOffice.ServiceManager" ) );

        if( ! rInstance.is() )
        {
            printf( "StarOffice.ServiceManager is not exported from remote counterpart\n" );
            return 1;
        }

        // query for the simpler XMultiServiceFactory interface, sufficient for scripting
        Reference< XMultiServiceFactory > rOfficeServiceManager (rInstance, UNO_QUERY);

        if( ! rInstance.is() )
        {
            printf( "XMultiServiceFactory interface is not exported for StarOffice.ServiceManager\n" );
            return 1;
        }

        printf( "Connected sucessfully to the office\n" );
    }
    catch( Exception &e )
    {
        OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
        printf( "Error: %s\n", o.pData->buffer );
        return 1;
    }
    return 0;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <assert.h>
#include <string.h>

#include <google/dense_hash_set>

#include <locale>
#include <list>
#include <iostream>
#include <string>

#include <re2/re2.h>

#include "smart_git.h"
#include "timer.h"

using google::dense_hash_set;
using re2::RE2;
using re2::StringPiece;
using namespace std;

#define CHUNK_SIZE (1 << 20)

class chunk_allocator {
public:
    chunk_allocator() : current_() {
        new_chunk();
    }

    char *alloc(size_t len) {
        assert(len < CHUNK_SIZE);
        if (alloc_ + len > end_)
            new_chunk();
        char *out = alloc_;
        alloc_ += len;
        return out;
    }

    list<StringPiece>::iterator begin () {
        return chunks_.begin();
    }

    list<StringPiece>::iterator end () {
        return chunks_.end();
    }

protected:
    void new_chunk() {
        if (current_ != 0)
            chunks_.push_back(StringPiece(current_, alloc_ - current_));
        current_ = new char[CHUNK_SIZE];
        alloc_ = current_;
        end_ = current_ + CHUNK_SIZE;
    }

    list<StringPiece> chunks_;
    char *current_;
    char *alloc_;
    char *end_;
};

/*
 * We special-case data() == NULL to provide an "empty" element for
 * dense_hash_set.
 *
 * StringPiece::operator== will consider a zero-length string equal to a
 * zero-length string with a NULL data().
 */
struct eqstr {
    bool operator()(const StringPiece& lhs, const StringPiece& rhs) const {
        if (lhs.data() == NULL && rhs.data() == NULL)
            return true;
        if (lhs.data() == NULL || rhs.data() == NULL)
            return false;
        return lhs == rhs;
    }
};

struct hashstr {
    locale loc;
    size_t operator()(const StringPiece &str) const {
        const collate<char> &coll = use_facet<collate<char> >(loc);
        return coll.hash(str.data(), str.data() + str.size());
    }
};

const StringPiece empty_string(NULL, 0);

typedef dense_hash_set<StringPiece, hashstr, eqstr> string_hash;

class code_counter {
public:
    code_counter(git_repository *repo)
        : repo_(repo), stats_()
    {
        lines_.set_empty_key(empty_string);
    }

    void walk_ref(const char *ref) {
        smart_object<git_commit> commit;
        smart_object<git_tree> tree;
        resolve_ref(commit, ref);
        git_commit_tree(tree, commit);

        walk_tree(tree);
    }

    void dump_stats() {
        printf("Bytes: %ld (dedup: %ld)\n", stats_.bytes, stats_.dedup_bytes);
        printf("Lines: %ld (dedup: %ld)\n", stats_.lines, stats_.dedup_lines);
    }

    bool match(RE2& pat) {
        list<StringPiece>::iterator it;
        StringPiece match;
        int matches = 0;

        for (it = alloc_.begin(); it != alloc_.end(); it++) {
            int pos = 0;
            while (pos < (*it).size()) {
                    if (!pat.Match(*it, pos, (*it).size(), RE2::UNANCHORED, &match, 1))
                        break;
                    assert(memchr(match.data(), '\n', match.size()) == NULL);
                    StringPiece line = find_line(*it, match);
                    printf("%.*s\n", line.size(), line.data());
                    pos = line.size() + line.data() - (*it).data();
                    if (++matches == 10)
                        return true;
                }
        }
        return matches > 0;
    }
protected:
    StringPiece find_line(const StringPiece& chunk, const StringPiece& match) {
        const char *start, *end;
        assert(match.data() >= chunk.data());
        assert(match.data() < chunk.data() + chunk.size());
        assert(match.size() < (chunk.size() - (match.data() - chunk.data())));
        start = static_cast<const char*>
            (memrchr(chunk.data(), '\n', match.data() - chunk.data()));
        if (start == NULL)
            start = chunk.data();
        else
            start++;
        end = static_cast<const char*>
            (memchr(match.data() + match.size(), '\n',
                    chunk.size() - (match.data() - chunk.data()) - match.size()));
        if (end == NULL)
            end = chunk.data() + chunk.size();
        return StringPiece(start, end - start);
    }

    void walk_tree(git_tree *tree) {
        int entries = git_tree_entrycount(tree);
        int i;
        for (i = 0; i < entries; i++) {
            const git_tree_entry *ent = git_tree_entry_byindex(tree, i);
            smart_object<git_object> obj;
            git_tree_entry_2object(obj, repo_, ent);
            if (git_tree_entry_type(ent) == GIT_OBJ_TREE) {
                walk_tree(obj);
            } else if (git_tree_entry_type(ent) == GIT_OBJ_BLOB) {
                update_stats(obj);
            }
        }
    }

    void update_stats(git_blob *blob) {
        size_t len = git_blob_rawsize(blob);
        const char *p = static_cast<const char*>(git_blob_rawcontent(blob));
        const char *end = p + len;
        const char *f;
        string_hash::iterator it;

        while ((f = static_cast<const char*>(memchr(p, '\n', end - p))) != 0) {
            it = lines_.find(StringPiece(p, f - p));
            if (it == lines_.end()) {
                stats_.dedup_bytes += (f - p) + 1;
                stats_.dedup_lines ++;

                // Include the trailing '\n' in the chunk buffer
                char *alloc = alloc_.alloc(f - p + 1);
                memcpy(alloc, p, f - p + 1);
                lines_.insert(StringPiece(alloc, f - p));
            }
            p = f + 1;
            stats_.lines++;
        }

        stats_.bytes += len;
    }

    void resolve_ref(smart_object<git_commit> &out, const char *refname) {
        git_reference *ref;
        const git_oid *oid;
        git_oid tmp;
        smart_object<git_object> obj;
        if (git_oid_fromstr(&tmp, refname) == GIT_SUCCESS) {
            git_object_lookup(obj, repo_, &tmp, GIT_OBJ_ANY);
        } else {
            git_reference_lookup(&ref, repo_, refname);
            git_reference_resolve(&ref, ref);
            oid = git_reference_oid(ref);
            git_object_lookup(obj, repo_, oid, GIT_OBJ_ANY);
        }
        if (git_object_type(obj) == GIT_OBJ_TAG) {
            git_tag_target(out, obj);
        } else {
            out = obj.release();
        }
    }

    git_repository *repo_;
    string_hash lines_;
    struct {
        unsigned long bytes, dedup_bytes;
        unsigned long lines, dedup_lines;
    } stats_;
    chunk_allocator alloc_;
};

int main(int argc, char **argv) {
    git_repository *repo;
    git_repository_open(&repo, ".git");

    code_counter counter(repo);

    for (int i = 1; i < argc; i++) {
        timer tm;
        struct timeval elapsed;
        printf("Walking %s...", argv[i]);
        fflush(stdout);
        counter.walk_ref(argv[i]);
        elapsed = tm.elapsed();
        printf(" done in %d.%06ds\n",
               (int)elapsed.tv_sec, (int)elapsed.tv_usec);
    }
    counter.dump_stats();
    RE2::Options opts;
    opts.set_never_nl(true);
    opts.set_one_line(false);
    opts.set_posix_syntax(true);
    while (true) {
        printf("regex> ");
        string line;
        getline(cin, line);
        if (cin.eof())
            break;
        RE2 re(line, opts);
        if (re.ok()) {
            timer tm;
            struct timeval elapsed;
            if (!counter.match(re)) {
                printf("no match\n");
            }
            elapsed = tm.elapsed();
            printf("Match completed in %d.%06ds.\n",
                   (int)elapsed.tv_sec, (int)elapsed.tv_usec);
        }
    }

    return 0;
}
<commit_msg>Actually include the most recently-added chunk in the search.<commit_after>#include <stdio.h>
#include <assert.h>
#include <string.h>

#include <google/dense_hash_set>

#include <locale>
#include <list>
#include <iostream>
#include <string>

#include <re2/re2.h>

#include "smart_git.h"
#include "timer.h"

using google::dense_hash_set;
using re2::RE2;
using re2::StringPiece;
using namespace std;

#define CHUNK_SIZE (1 << 20)

class chunk_allocator {
public:
    chunk_allocator() : current_() {
        new_chunk();
    }

    char *alloc(size_t len) {
        assert(len < CHUNK_SIZE);
        if (alloc_ + len > end_)
            new_chunk();
        char *out = alloc_;
        alloc_ += len;
        return out;
    }

    list<StringPiece>::iterator begin () {
        return chunks_.begin();
    }

    list<StringPiece>::iterator end () {
        return chunks_.end();
    }

    void finish(void) {
        new_chunk();
    }

protected:
    void new_chunk() {
        if (current_ != 0)
            chunks_.push_back(StringPiece(current_, alloc_ - current_));
        current_ = new char[CHUNK_SIZE];
        alloc_ = current_;
        end_ = current_ + CHUNK_SIZE;
    }

    list<StringPiece> chunks_;
    char *current_;
    char *alloc_;
    char *end_;
};

/*
 * We special-case data() == NULL to provide an "empty" element for
 * dense_hash_set.
 *
 * StringPiece::operator== will consider a zero-length string equal to a
 * zero-length string with a NULL data().
 */
struct eqstr {
    bool operator()(const StringPiece& lhs, const StringPiece& rhs) const {
        if (lhs.data() == NULL && rhs.data() == NULL)
            return true;
        if (lhs.data() == NULL || rhs.data() == NULL)
            return false;
        return lhs == rhs;
    }
};

struct hashstr {
    locale loc;
    size_t operator()(const StringPiece &str) const {
        const collate<char> &coll = use_facet<collate<char> >(loc);
        return coll.hash(str.data(), str.data() + str.size());
    }
};

const StringPiece empty_string(NULL, 0);

typedef dense_hash_set<StringPiece, hashstr, eqstr> string_hash;

class code_counter {
public:
    code_counter(git_repository *repo)
        : repo_(repo), stats_()
    {
        lines_.set_empty_key(empty_string);
    }

    void walk_ref(const char *ref) {
        smart_object<git_commit> commit;
        smart_object<git_tree> tree;
        resolve_ref(commit, ref);
        git_commit_tree(tree, commit);

        walk_tree(tree);
    }

    void dump_stats() {
        printf("Bytes: %ld (dedup: %ld)\n", stats_.bytes, stats_.dedup_bytes);
        printf("Lines: %ld (dedup: %ld)\n", stats_.lines, stats_.dedup_lines);
    }

    bool match(RE2& pat) {
        list<StringPiece>::iterator it;
        StringPiece match;
        int matches = 0;
        alloc_.finish();

        for (it = alloc_.begin(); it != alloc_.end(); it++) {
            int pos = 0;
            while (pos < (*it).size()) {
                    if (!pat.Match(*it, pos, (*it).size(), RE2::UNANCHORED, &match, 1))
                        break;
                    assert(memchr(match.data(), '\n', match.size()) == NULL);
                    StringPiece line = find_line(*it, match);
                    printf("%.*s\n", line.size(), line.data());
                    pos = line.size() + line.data() - (*it).data();
                    if (++matches == 10)
                        return true;
                }
        }
        return matches > 0;
    }
protected:
    StringPiece find_line(const StringPiece& chunk, const StringPiece& match) {
        const char *start, *end;
        assert(match.data() >= chunk.data());
        assert(match.data() < chunk.data() + chunk.size());
        assert(match.size() < (chunk.size() - (match.data() - chunk.data())));
        start = static_cast<const char*>
            (memrchr(chunk.data(), '\n', match.data() - chunk.data()));
        if (start == NULL)
            start = chunk.data();
        else
            start++;
        end = static_cast<const char*>
            (memchr(match.data() + match.size(), '\n',
                    chunk.size() - (match.data() - chunk.data()) - match.size()));
        if (end == NULL)
            end = chunk.data() + chunk.size();
        return StringPiece(start, end - start);
    }

    void walk_tree(git_tree *tree) {
        int entries = git_tree_entrycount(tree);
        int i;
        for (i = 0; i < entries; i++) {
            const git_tree_entry *ent = git_tree_entry_byindex(tree, i);
            smart_object<git_object> obj;
            git_tree_entry_2object(obj, repo_, ent);
            if (git_tree_entry_type(ent) == GIT_OBJ_TREE) {
                walk_tree(obj);
            } else if (git_tree_entry_type(ent) == GIT_OBJ_BLOB) {
                update_stats(obj);
            }
        }
    }

    void update_stats(git_blob *blob) {
        size_t len = git_blob_rawsize(blob);
        const char *p = static_cast<const char*>(git_blob_rawcontent(blob));
        const char *end = p + len;
        const char *f;
        string_hash::iterator it;

        while ((f = static_cast<const char*>(memchr(p, '\n', end - p))) != 0) {
            it = lines_.find(StringPiece(p, f - p));
            if (it == lines_.end()) {
                stats_.dedup_bytes += (f - p) + 1;
                stats_.dedup_lines ++;

                // Include the trailing '\n' in the chunk buffer
                char *alloc = alloc_.alloc(f - p + 1);
                memcpy(alloc, p, f - p + 1);
                lines_.insert(StringPiece(alloc, f - p));
            }
            p = f + 1;
            stats_.lines++;
        }

        stats_.bytes += len;
    }

    void resolve_ref(smart_object<git_commit> &out, const char *refname) {
        git_reference *ref;
        const git_oid *oid;
        git_oid tmp;
        smart_object<git_object> obj;
        if (git_oid_fromstr(&tmp, refname) == GIT_SUCCESS) {
            git_object_lookup(obj, repo_, &tmp, GIT_OBJ_ANY);
        } else {
            git_reference_lookup(&ref, repo_, refname);
            git_reference_resolve(&ref, ref);
            oid = git_reference_oid(ref);
            git_object_lookup(obj, repo_, oid, GIT_OBJ_ANY);
        }
        if (git_object_type(obj) == GIT_OBJ_TAG) {
            git_tag_target(out, obj);
        } else {
            out = obj.release();
        }
    }

    git_repository *repo_;
    string_hash lines_;
    struct {
        unsigned long bytes, dedup_bytes;
        unsigned long lines, dedup_lines;
    } stats_;
    chunk_allocator alloc_;
};

int main(int argc, char **argv) {
    git_repository *repo;
    git_repository_open(&repo, ".git");

    code_counter counter(repo);

    for (int i = 1; i < argc; i++) {
        timer tm;
        struct timeval elapsed;
        printf("Walking %s...", argv[i]);
        fflush(stdout);
        counter.walk_ref(argv[i]);
        elapsed = tm.elapsed();
        printf(" done in %d.%06ds\n",
               (int)elapsed.tv_sec, (int)elapsed.tv_usec);
    }
    counter.dump_stats();
    RE2::Options opts;
    opts.set_never_nl(true);
    opts.set_one_line(false);
    opts.set_posix_syntax(true);
    while (true) {
        printf("regex> ");
        string line;
        getline(cin, line);
        if (cin.eof())
            break;
        RE2 re(line, opts);
        if (re.ok()) {
            timer tm;
            struct timeval elapsed;
            if (!counter.match(re)) {
                printf("no match\n");
            }
            elapsed = tm.elapsed();
            printf("Match completed in %d.%06ds.\n",
                   (int)elapsed.tv_sec, (int)elapsed.tv_usec);
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "Karabiner-VirtualHIDDevice/dist/include/karabiner_virtual_hid_device.hpp"
#include "hid_manager.hpp"

namespace {
class hid_set_report final {
public:
  hid_set_report(const hid_set_report&) = delete;

  hid_set_report(void) : hid_manager_({
                             std::make_pair(krbn::hid_usage_page::generic_desktop, krbn::hid_usage::gd_keyboard),
                         }) {
    hid_manager_.device_detected.connect([](auto&& human_interface_device) {
      auto r = human_interface_device->open();
      if (r != kIOReturnSuccess) {
        krbn::logger::get_logger().error("failed to open");
        return;
      }

      {
        pqrs::karabiner_virtual_hid_device::hid_report::keyboard_input keyboard_input;
        const uint8_t* report = reinterpret_cast<const uint8_t*>(&keyboard_input);

        auto kr = human_interface_device->set_report(kIOHIDReportTypeInput,
                                                     report[0],
                                                     report,
                                                     sizeof(keyboard_input));
        if (kr != kIOReturnSuccess) {
          krbn::logger::get_logger().error("Failed to IOHIDDeviceSetReport: {0}",
                                           krbn::iokit_utility::get_error_name(kr));
          return;
        }
      }

      human_interface_device->close();
    });

    hid_manager_.start();
  }

  ~hid_set_report(void) {
    hid_manager_.stop();
  }

private:
  krbn::hid_manager hid_manager_;
};
} // namespace

int main(int argc, const char* argv[]) {
  krbn::thread_utility::register_main_thread();

  hid_set_report hid_set_report;
  CFRunLoopRun();
  return 0;
}
<commit_msg>update appendix/hid_set_report<commit_after>#include "Karabiner-VirtualHIDDevice/dist/include/karabiner_virtual_hid_device.hpp"
#include "hid_manager.hpp"

namespace {
class hid_set_report final {
public:
  hid_set_report(const hid_set_report&) = delete;

  hid_set_report(void) {
    std::vector<std::pair<krbn::hid_usage_page, krbn::hid_usage>> targets({
        std::make_pair(krbn::hid_usage_page::generic_desktop, krbn::hid_usage::gd_keyboard),
    });

    hid_manager_ = std::make_unique<krbn::hid_manager>(targets);

    hid_manager_->device_detected.connect([](auto&& weak_hid) {
      if (auto hid = weak_hid.lock()) {
        hid->opened.connect([weak_hid] {
          if (auto hid = weak_hid.lock()) {
            pqrs::karabiner_virtual_hid_device::hid_report::keyboard_input keyboard_input;
            const uint8_t* report = reinterpret_cast<const uint8_t*>(&keyboard_input);

            hid->async_set_report(kIOHIDReportTypeInput,
                                  report[0],
                                  report,
                                  sizeof(keyboard_input));
            krbn::logger::get_logger().info("async_set_report is called {0}", hid->get_name_for_log());
          }
        });

        hid->open_failed.connect([weak_hid](auto&& error_code) {
          if (auto hid = weak_hid.lock()) {
            krbn::logger::get_logger().error("failed to open {0}", hid->get_name_for_log());
          }
        });

        hid->async_open();
      }
    });

    hid_manager_->async_start();
  }

  ~hid_set_report(void) {
    hid_manager_ = nullptr;
  }

private:
  std::unique_ptr<krbn::hid_manager> hid_manager_;
};
} // namespace

int main(int argc, const char* argv[]) {
  krbn::thread_utility::register_main_thread();

  signal(SIGINT, [](int) {
    CFRunLoopStop(CFRunLoopGetMain());
  });

  hid_set_report hid_set_report;

  CFRunLoopRun();

  return 0;
}
<|endoftext|>