<commit_before>/*
 Copyright (c) 2017, 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 "remote_control/commands/set_interior_vehicle_data_request.h"
#include <algorithm>
#include "remote_control/rc_module_constants.h"
#include "remote_control/message_helper.h"
#include "functional_module/function_ids.h"
#include "json/json.h"
#include "utils/helpers.h"

namespace remote_control {

namespace commands {

using namespace json_keys;
using namespace message_params;

namespace {
std::vector<std::string> GetModuleReadOnlyParams(
    const std::string& module_type) {
  std::vector<std::string> module_ro_params;
  if (enums_value::kClimate == module_type) {
    module_ro_params.push_back(kCurrentTemperature);
  } else if (enums_value::kRadio == module_type) {
    module_ro_params.push_back(kRdsData);
    module_ro_params.push_back(kAvailableHDs);
    module_ro_params.push_back(kSignalStrength);
    module_ro_params.push_back(kSignalChangeThreshold);
    module_ro_params.push_back(kState);
  }
  return module_ro_params;
}

const std::map<std::string, std::string> GetModuleDataToCapabilitiesMapping() {
  std::map<std::string, std::string> mapping;
  // climate
  mapping["fanSpeed"] = "fanSpeedAvailable";
  mapping["currentTemperature"] = "currentTemperatureAvailable";
  mapping["desiredTemperature"] = "desiredTemperatureAvailable";
  mapping["acEnable"] = "acEnableAvailable";
  mapping["circulateAirEnable"] = "circulateAirEnableAvailable";
  mapping["autoModeEnable"] = "autoModeEnableAvailable";
  mapping["defrostZone"] = "defrostZoneAvailable";
  mapping["dualModeEnable"] = "dualModeEnableAvailable";
  mapping["acMaxEnable"] = "acMaxEnableAvailable";
  mapping["ventilationMode"] = "ventilationModeAvailable";

  // radio
  mapping["band"] = "radioBandAvailable";
  mapping["frequencyInteger"] = "radioFrequencyAvailable";
  mapping["frequencyFraction"] = "radioFrequencyAvailable";
  mapping["rdsData"] = "rdsDataAvailable";
  mapping["availableHDs"] = "availableHDsAvailable";
  mapping["hdChannel"] = "availableHDsAvailable";
  mapping["signalStrength"] = "signalStrengthAvailable";
  mapping["radioEnable"] = "radioEnableAvailable";
  mapping["state"] = "stateAvailable";

  return mapping;
}
}  // namespace

CREATE_LOGGERPTR_GLOBAL(logger_, "SetInteriorVehicleDataRequest")

SetInteriorVehicleDataRequest::SetInteriorVehicleDataRequest(
    const application_manager::MessagePtr& message,
    RemotePluginInterface& rc_module)
    : BaseCommandRequest(message, rc_module) {}

SetInteriorVehicleDataRequest::~SetInteriorVehicleDataRequest() {}

bool CheckControlDataByCapabilities(
    const smart_objects::SmartObject& module_caps,
    const Json::Value& control_data) {
  std::map<std::string, std::string> mapping =
      GetModuleDataToCapabilitiesMapping();
  Json::Value::Members control_data_keys = control_data.getMemberNames();

  Json::Value::Members::const_iterator it = control_data_keys.begin();
  for (; it != control_data_keys.end(); ++it) {
    const std::string& caps_key = mapping[*it];
    DCHECK_OR_RETURN(module_caps.keyExists(caps_key), false);
    if (!module_caps[caps_key].asBool()) {
      return false;
    }
  }
  return true;
}

bool CheckIfModuleDataExistInCapabilities(
    const smart_objects::SmartObject& rc_capabilities,
    const Json::Value& module_data) {
  if (rc_capabilities.keyExists(strings::kradioControlCapabilities)) {
    const smart_objects::SmartObject& radio_caps =
        rc_capabilities[strings::kradioControlCapabilities];
    return CheckControlDataByCapabilities(
        radio_caps, module_data[strings::kRadioControlData]);
  }
  if (rc_capabilities.keyExists(strings::kclimateControlCapabilities)) {
    const smart_objects::SmartObject& climate_caps =
        rc_capabilities[strings::kclimateControlCapabilities];
    return CheckControlDataByCapabilities(
        climate_caps, module_data[strings::kClimateControlData]);
  }
  DCHECK(false && "Module Data does not contains control data");
  return true;
}

void SetInteriorVehicleDataRequest::Execute() {
  LOG4CXX_AUTO_TRACE(logger_);

  Json::Value request_params =
      MessageHelper::StringToValue(message_->json_message());
  const Json::Value module_data = request_params[kModuleData];
  const std::string module_type = module_data[kModuleType].asString();
  bool module_type_and_data_match = true;

  if (enums_value::kRadio == module_type) {
    module_type_and_data_match = !IsMember(module_data, kClimateControlData);
  }

  if (enums_value::kClimate == module_type) {
    module_type_and_data_match = !IsMember(module_data, kRadioControlData);
  }

  if (module_type_and_data_match) {
    if (!CheckIfModuleDataExistInCapabilities(*(service()->GetRCCapabilities()),
                                              module_data)) {
      LOG4CXX_WARN(logger_, "Accessing not supported module data");
      SendResponse(false,
                   result_codes::kUnsupportedResource,
                   "Accessing not supported module data");
      return;
    }
    if (AreAllParamsReadOnly(request_params)) {
      LOG4CXX_WARN(logger_, "All request params in module type are READ ONLY!");
      SendResponse(false,
                   result_codes::kReadOnly,
                   "All request params in module type are READ ONLY!");
      return;
    }
    if (AreReadOnlyParamsPresent(request_params)) {
      LOG4CXX_DEBUG(logger_, "Request module type has READ ONLY parameters");
      LOG4CXX_DEBUG(logger_, "Cutting-off READ ONLY parameters... ");
      CutOffReadOnlyParams(request_params);
    }
    application_manager::MessagePtr hmi_request = CreateHmiRequest(
        functional_modules::hmi_api::set_interior_vehicle_data, request_params);
    service()->RemoveHMIFakeParameters(hmi_request);
    SendMessageToHMI(hmi_request);
  } else {
    LOG4CXX_WARN(logger_, "Request module type & data mismatch!");
    SendResponse(false,
                 result_codes::kInvalidData,
                 "Request module type & data mismatch!");
  }
}

AcquireResult::eType SetInteriorVehicleDataRequest::AcquireResource(
    const Json::Value& message) {
  return rc_module_.resource_allocation_manager().AcquireResource(
      ModuleType(message), app()->app_id());
}

bool SetInteriorVehicleDataRequest::IsResourceFree(
    const std::string& module_type) const {
  return rc_module_.resource_allocation_manager().IsResourceFree(module_type);
}

void SetInteriorVehicleDataRequest::SetResourceState(
    const Json::Value& message, const ResourceState::eType state) {
  const std::string& module_type = ModuleType(message);
  const uint32_t app_id = app()->app_id();

  ResourceAllocationManager& allocation_manager =
      rc_module_.resource_allocation_manager();

  allocation_manager.SetResourceState(module_type, app_id, state);
}

bool SetInteriorVehicleDataRequest::AreReadOnlyParamsPresent(
    const Json::Value& request_params) {
  LOG4CXX_AUTO_TRACE(logger_);
  std::vector<std::string> module_type_params = ControlData(request_params);
  std::vector<std::string>::iterator it = module_type_params.begin();
  std::vector<std::string> ro_params =
      GetModuleReadOnlyParams(ModuleType(request_params));
  for (; it != module_type_params.end(); ++it) {
    if (helpers::in_range(ro_params, *it)) {
      return true;
    }
  }
  return false;
}

void SetInteriorVehicleDataRequest::CutOffReadOnlyParams(
    Json::Value& request_params) {
  LOG4CXX_AUTO_TRACE(logger_);
  std::vector<std::string> module_type_params = ControlData(request_params);
  std::vector<std::string>::iterator it = module_type_params.begin();
  const std::string module_type = ModuleType(request_params);
  std::vector<std::string> ro_params = GetModuleReadOnlyParams(module_type);
  for (; it != module_type_params.end(); ++it) {
    if (helpers::in_range(ro_params, *it)) {
      if (enums_value::kClimate == module_type) {
        request_params[message_params::kModuleData]
                      [message_params::kClimateControlData].removeMember(*it);
        LOG4CXX_DEBUG(logger_, "Cutting-off READ ONLY parameter: " << *it);
      } else if (enums_value::kRadio == module_type) {
        request_params[message_params::kModuleData]
                      [message_params::kRadioControlData].removeMember(*it);
        LOG4CXX_DEBUG(logger_, "Cutting-off READ ONLY parameter: " << *it);
      }
    }
  }
}

bool SetInteriorVehicleDataRequest::AreAllParamsReadOnly(
    const Json::Value& request_params) {
  LOG4CXX_AUTO_TRACE(logger_);
  std::vector<std::string> module_type_params = ControlData(request_params);
  std::vector<std::string>::iterator it = module_type_params.begin();
  std::vector<std::string> ro_params =
      GetModuleReadOnlyParams(ModuleType(request_params));
  for (; it != module_type_params.end(); ++it) {
    if (!helpers::in_range(ro_params, *it)) {
      return false;
    }
  }
  return true;
}

void SetInteriorVehicleDataRequest::OnEvent(
    const rc_event_engine::Event<application_manager::MessagePtr, std::string>&
        event) {
  LOG4CXX_AUTO_TRACE(logger_);
  DCHECK_OR_RETURN_VOID(
      (functional_modules::hmi_api::set_interior_vehicle_data == event.id()));

  application_manager::Message& hmi_response = *(event.event_message());
  if (application_manager::MessageValidationResult::SUCCESS !=
      service()->ValidateMessageBySchema(hmi_response)) {
    SendResponse(false, result_codes::kGenericError, "");
    return;
  }

  LOG4CXX_DEBUG(logger_, "HMI response is valid");
  const Json::Value value =
      MessageHelper::StringToValue(hmi_response.json_message());

  std::string result_code;
  std::string info;

  const bool is_response_successful = ParseResultCode(value, result_code, info);

  if (is_response_successful) {
    response_params_[kModuleData] = value[kResult][kModuleData];
  }

  SendResponse(is_response_successful, result_code.c_str(), info);
}

std::string SetInteriorVehicleDataRequest::ModuleType(
    const Json::Value& message) {
  const Json::Value& module_data =
      message.get(message_params::kModuleData, Json::Value(Json::objectValue));
  return module_data.get(message_params::kModuleType, "").asString();
}

std::vector<std::string> SetInteriorVehicleDataRequest::ControlData(
    const Json::Value& message) {
  Json::Value data =
      message.get(message_params::kModuleData, Json::Value(Json::objectValue));
  const char* name_control_data;
  std::string module = ModuleType(message);
  if (module == enums_value::kRadio) {
    name_control_data = message_params::kRadioControlData;
  }
  if (module == enums_value::kClimate) {
    name_control_data = message_params::kClimateControlData;
  }
  Json::Value params =
      data.get(name_control_data, Json::Value(Json::objectValue));
  return params.getMemberNames();
}

}  // namespace commands

}  // namespace remote_control
<commit_msg>Chack capabilities only if capabilities exist<commit_after>/*
 Copyright (c) 2017, 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 "remote_control/commands/set_interior_vehicle_data_request.h"
#include <algorithm>
#include "remote_control/rc_module_constants.h"
#include "remote_control/message_helper.h"
#include "functional_module/function_ids.h"
#include "json/json.h"
#include "utils/helpers.h"

namespace remote_control {

namespace commands {

using namespace json_keys;
using namespace message_params;

namespace {
std::vector<std::string> GetModuleReadOnlyParams(
    const std::string& module_type) {
  std::vector<std::string> module_ro_params;
  if (enums_value::kClimate == module_type) {
    module_ro_params.push_back(kCurrentTemperature);
  } else if (enums_value::kRadio == module_type) {
    module_ro_params.push_back(kRdsData);
    module_ro_params.push_back(kAvailableHDs);
    module_ro_params.push_back(kSignalStrength);
    module_ro_params.push_back(kSignalChangeThreshold);
    module_ro_params.push_back(kState);
  }
  return module_ro_params;
}

const std::map<std::string, std::string> GetModuleDataToCapabilitiesMapping() {
  std::map<std::string, std::string> mapping;
  // climate
  mapping["fanSpeed"] = "fanSpeedAvailable";
  mapping["currentTemperature"] = "currentTemperatureAvailable";
  mapping["desiredTemperature"] = "desiredTemperatureAvailable";
  mapping["acEnable"] = "acEnableAvailable";
  mapping["circulateAirEnable"] = "circulateAirEnableAvailable";
  mapping["autoModeEnable"] = "autoModeEnableAvailable";
  mapping["defrostZone"] = "defrostZoneAvailable";
  mapping["dualModeEnable"] = "dualModeEnableAvailable";
  mapping["acMaxEnable"] = "acMaxEnableAvailable";
  mapping["ventilationMode"] = "ventilationModeAvailable";

  // radio
  mapping["band"] = "radioBandAvailable";
  mapping["frequencyInteger"] = "radioFrequencyAvailable";
  mapping["frequencyFraction"] = "radioFrequencyAvailable";
  mapping["rdsData"] = "rdsDataAvailable";
  mapping["availableHDs"] = "availableHDsAvailable";
  mapping["hdChannel"] = "availableHDsAvailable";
  mapping["signalStrength"] = "signalStrengthAvailable";
  mapping["radioEnable"] = "radioEnableAvailable";
  mapping["state"] = "stateAvailable";

  return mapping;
}
}  // namespace

CREATE_LOGGERPTR_GLOBAL(logger_, "SetInteriorVehicleDataRequest")

SetInteriorVehicleDataRequest::SetInteriorVehicleDataRequest(
    const application_manager::MessagePtr& message,
    RemotePluginInterface& rc_module)
    : BaseCommandRequest(message, rc_module) {}

SetInteriorVehicleDataRequest::~SetInteriorVehicleDataRequest() {}

bool CheckControlDataByCapabilities(
    const smart_objects::SmartObject& module_caps,
    const Json::Value& control_data) {
  std::map<std::string, std::string> mapping =
      GetModuleDataToCapabilitiesMapping();
  Json::Value::Members control_data_keys = control_data.getMemberNames();

  Json::Value::Members::const_iterator it = control_data_keys.begin();
  for (; it != control_data_keys.end(); ++it) {
    const std::string& caps_key = mapping[*it];
    DCHECK_OR_RETURN(module_caps.keyExists(caps_key), false);
    if (!module_caps[caps_key].asBool()) {
      return false;
    }
  }
  return true;
}

bool CheckIfModuleDataExistInCapabilities(
    const smart_objects::SmartObject& rc_capabilities,
    const Json::Value& module_data) {
  if (rc_capabilities.keyExists(strings::kradioControlCapabilities)) {
    const smart_objects::SmartObject& radio_caps =
        rc_capabilities[strings::kradioControlCapabilities];
    return CheckControlDataByCapabilities(
        radio_caps, module_data[strings::kRadioControlData]);
  }
  if (rc_capabilities.keyExists(strings::kclimateControlCapabilities)) {
    const smart_objects::SmartObject& climate_caps =
        rc_capabilities[strings::kclimateControlCapabilities];
    return CheckControlDataByCapabilities(
        climate_caps, module_data[strings::kClimateControlData]);
  }
  DCHECK(false && "Module Data does not contains control data");
  return true;
}

void SetInteriorVehicleDataRequest::Execute() {
  LOG4CXX_AUTO_TRACE(logger_);

  Json::Value request_params =
      MessageHelper::StringToValue(message_->json_message());
  const Json::Value module_data = request_params[kModuleData];
  const std::string module_type = module_data[kModuleType].asString();
  bool module_type_and_data_match = true;

  if (enums_value::kRadio == module_type) {
    module_type_and_data_match = !IsMember(module_data, kClimateControlData);
  }

  if (enums_value::kClimate == module_type) {
    module_type_and_data_match = !IsMember(module_data, kRadioControlData);
  }

  if (module_type_and_data_match) {
    const smart_objects::SmartObject* capabilities =
        service()->GetRCCapabilities();
    if (capabilities &&
        !CheckIfModuleDataExistInCapabilities(*capabilities, module_data)) {
      LOG4CXX_WARN(logger_, "Accessing not supported module data");
      SendResponse(false,
                   result_codes::kUnsupportedResource,
                   "Accessing not supported module data");
      return;
    }
    if (AreAllParamsReadOnly(request_params)) {
      LOG4CXX_WARN(logger_, "All request params in module type are READ ONLY!");
      SendResponse(false,
                   result_codes::kReadOnly,
                   "All request params in module type are READ ONLY!");
      return;
    }
    if (AreReadOnlyParamsPresent(request_params)) {
      LOG4CXX_DEBUG(logger_, "Request module type has READ ONLY parameters");
      LOG4CXX_DEBUG(logger_, "Cutting-off READ ONLY parameters... ");
      CutOffReadOnlyParams(request_params);
    }
    application_manager::MessagePtr hmi_request = CreateHmiRequest(
        functional_modules::hmi_api::set_interior_vehicle_data, request_params);
    service()->RemoveHMIFakeParameters(hmi_request);
    SendMessageToHMI(hmi_request);
  } else {
    LOG4CXX_WARN(logger_, "Request module type & data mismatch!");
    SendResponse(false,
                 result_codes::kInvalidData,
                 "Request module type & data mismatch!");
  }
}

AcquireResult::eType SetInteriorVehicleDataRequest::AcquireResource(
    const Json::Value& message) {
  return rc_module_.resource_allocation_manager().AcquireResource(
      ModuleType(message), app()->app_id());
}

bool SetInteriorVehicleDataRequest::IsResourceFree(
    const std::string& module_type) const {
  return rc_module_.resource_allocation_manager().IsResourceFree(module_type);
}

void SetInteriorVehicleDataRequest::SetResourceState(
    const Json::Value& message, const ResourceState::eType state) {
  const std::string& module_type = ModuleType(message);
  const uint32_t app_id = app()->app_id();

  ResourceAllocationManager& allocation_manager =
      rc_module_.resource_allocation_manager();

  allocation_manager.SetResourceState(module_type, app_id, state);
}

bool SetInteriorVehicleDataRequest::AreReadOnlyParamsPresent(
    const Json::Value& request_params) {
  LOG4CXX_AUTO_TRACE(logger_);
  std::vector<std::string> module_type_params = ControlData(request_params);
  std::vector<std::string>::iterator it = module_type_params.begin();
  std::vector<std::string> ro_params =
      GetModuleReadOnlyParams(ModuleType(request_params));
  for (; it != module_type_params.end(); ++it) {
    if (helpers::in_range(ro_params, *it)) {
      return true;
    }
  }
  return false;
}

void SetInteriorVehicleDataRequest::CutOffReadOnlyParams(
    Json::Value& request_params) {
  LOG4CXX_AUTO_TRACE(logger_);
  std::vector<std::string> module_type_params = ControlData(request_params);
  std::vector<std::string>::iterator it = module_type_params.begin();
  const std::string module_type = ModuleType(request_params);
  std::vector<std::string> ro_params = GetModuleReadOnlyParams(module_type);
  for (; it != module_type_params.end(); ++it) {
    if (helpers::in_range(ro_params, *it)) {
      if (enums_value::kClimate == module_type) {
        request_params[message_params::kModuleData]
                      [message_params::kClimateControlData].removeMember(*it);
        LOG4CXX_DEBUG(logger_, "Cutting-off READ ONLY parameter: " << *it);
      } else if (enums_value::kRadio == module_type) {
        request_params[message_params::kModuleData]
                      [message_params::kRadioControlData].removeMember(*it);
        LOG4CXX_DEBUG(logger_, "Cutting-off READ ONLY parameter: " << *it);
      }
    }
  }
}

bool SetInteriorVehicleDataRequest::AreAllParamsReadOnly(
    const Json::Value& request_params) {
  LOG4CXX_AUTO_TRACE(logger_);
  std::vector<std::string> module_type_params = ControlData(request_params);
  std::vector<std::string>::iterator it = module_type_params.begin();
  std::vector<std::string> ro_params =
      GetModuleReadOnlyParams(ModuleType(request_params));
  for (; it != module_type_params.end(); ++it) {
    if (!helpers::in_range(ro_params, *it)) {
      return false;
    }
  }
  return true;
}

void SetInteriorVehicleDataRequest::OnEvent(
    const rc_event_engine::Event<application_manager::MessagePtr, std::string>&
        event) {
  LOG4CXX_AUTO_TRACE(logger_);
  DCHECK_OR_RETURN_VOID(
      (functional_modules::hmi_api::set_interior_vehicle_data == event.id()));

  application_manager::Message& hmi_response = *(event.event_message());
  if (application_manager::MessageValidationResult::SUCCESS !=
      service()->ValidateMessageBySchema(hmi_response)) {
    SendResponse(false, result_codes::kGenericError, "");
    return;
  }

  LOG4CXX_DEBUG(logger_, "HMI response is valid");
  const Json::Value value =
      MessageHelper::StringToValue(hmi_response.json_message());

  std::string result_code;
  std::string info;

  const bool is_response_successful = ParseResultCode(value, result_code, info);

  if (is_response_successful) {
    response_params_[kModuleData] = value[kResult][kModuleData];
  }

  SendResponse(is_response_successful, result_code.c_str(), info);
}

std::string SetInteriorVehicleDataRequest::ModuleType(
    const Json::Value& message) {
  const Json::Value& module_data =
      message.get(message_params::kModuleData, Json::Value(Json::objectValue));
  return module_data.get(message_params::kModuleType, "").asString();
}

std::vector<std::string> SetInteriorVehicleDataRequest::ControlData(
    const Json::Value& message) {
  Json::Value data =
      message.get(message_params::kModuleData, Json::Value(Json::objectValue));
  const char* name_control_data;
  std::string module = ModuleType(message);
  if (module == enums_value::kRadio) {
    name_control_data = message_params::kRadioControlData;
  }
  if (module == enums_value::kClimate) {
    name_control_data = message_params::kClimateControlData;
  }
  Json::Value params =
      data.get(name_control_data, Json::Value(Json::objectValue));
  return params.getMemberNames();
}

}  // namespace commands

}  // namespace remote_control
<|endoftext|>


<commit_before>// render.cpp
#include "renderer-shared.h"
#include "../../source/core/slang-math.h"

#include "d3d11/render-d3d11.h"
#include "d3d12/render-d3d12.h"
#include "open-gl/render-gl.h"
#include "vulkan/render-vk.h"
#include "cuda/render-cuda.h"
#include "cpu/render-cpu.h"
#include <cstring>

namespace gfx {
using namespace Slang;

static const IResource::DescBase s_emptyDescBase = {};

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Global Renderer Functions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

static const uint8_t s_formatSize[] = {
    0, // Unknown,

    uint8_t(sizeof(float) * 4), // RGBA_Float32,
    uint8_t(sizeof(float) * 3), // RGB_Float32,
    uint8_t(sizeof(float) * 2), // RG_Float32,
    uint8_t(sizeof(float) * 1), // R_Float32,

    uint8_t(sizeof(uint32_t)), // RGBA_Unorm_UInt8,
    uint8_t(sizeof(uint32_t)), // BGRA_Unorm_UInt8,

    uint8_t(sizeof(uint16_t)), // R_UInt16,
    uint8_t(sizeof(uint32_t)), // R_UInt32,

    uint8_t(sizeof(float)), // D_Float32,
    uint8_t(sizeof(uint32_t)), // D_Unorm24_S8,
};

static void _compileTimeAsserts()
{
    SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(s_formatSize) == int(Format::CountOf));
}

extern "C"
{
    size_t SLANG_MCALL gfxGetFormatSize(Format format)
    {
        return s_formatSize[int(format)];
    }

    SLANG_GFX_API SlangResult SLANG_MCALL
        gfxCreateDevice(const IDevice::Desc* desc, IDevice** outDevice)
    {
        switch (desc->deviceType)
        {
#if SLANG_WINDOWS_FAMILY
        case DeviceType::DirectX11:
            {
                return createD3D11Device(desc, outDevice);
            }
        case DeviceType::DirectX12:
            {
                return createD3D12Device(desc, outDevice);
            }
        case DeviceType::OpenGl:
            {
                return createGLDevice(desc, outDevice);
            }
        case DeviceType::Vulkan:
            {
                return createVKDevice(desc, outDevice);
            }
        case DeviceType::CUDA:
            {
                return createCUDADevice(desc, outDevice);
            }
        case DeviceType::Default:
            {
                IDevice::Desc newDesc = *desc;
                newDesc.deviceType = DeviceType::DirectX12;
                if (gfxCreateDevice(&newDesc, outDevice) == SLANG_OK)
                    return SLANG_OK;
                newDesc.deviceType = DeviceType::Vulkan;
                if (gfxCreateDevice(&newDesc, outDevice) == SLANG_OK)
                    return SLANG_OK;
                newDesc.deviceType = DeviceType::DirectX11;
                if (gfxCreateDevice(&newDesc, outDevice) == SLANG_OK)
                    return SLANG_OK;
                newDesc.deviceType = DeviceType::OpenGl;
                if (gfxCreateDevice(&newDesc, outDevice) == SLANG_OK)
                    return SLANG_OK;
                return SLANG_FAIL;
            }
            break;
#elif SLANG_LINUX_FAMILY
        case DeviceType::Default:
        case DeviceType::Vulkan:
        {
            return createVKDevice(desc, outDevice);
        }
        case DeviceType::CUDA:
        {
            return createCUDADevice(desc, outDevice);
        }
#endif
        case DeviceType::CPU:
            {
                return createCPUDevice(desc, outDevice);
            }
            break;

        default:
            return SLANG_FAIL;
        }
    }

    const char* SLANG_MCALL gfxGetDeviceTypeName(DeviceType type)
    {
        switch (type)
        {
        case gfx::DeviceType::Unknown:
            return "Unknown";
        case gfx::DeviceType::Default:
            return "Default";
        case gfx::DeviceType::DirectX11:
            return "DirectX11";
        case gfx::DeviceType::DirectX12:
            return "DirectX12";
        case gfx::DeviceType::OpenGl:
            return "OpenGL";
        case gfx::DeviceType::Vulkan:
            return "Vulkan";
        case gfx::DeviceType::CPU:
            return "CPU";
        case gfx::DeviceType::CUDA:
            return "CUDA";
        default:
            return "?";
        }
    }

    void SLANG_MCALL gfxGetIdentityProjection(ProjectionStyle style, float projMatrix[16])
    {
        switch (style)
        {
        case ProjectionStyle::DirectX:
        case ProjectionStyle::OpenGl:
            {
                static const float kIdentity[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
                ::memcpy(projMatrix, kIdentity, sizeof(kIdentity));
                break;
            }
        case ProjectionStyle::Vulkan:
            {
                static const float kIdentity[] = {1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
                ::memcpy(projMatrix, kIdentity, sizeof(kIdentity));
                break;
            }
        default:
            {
                assert(!"Not handled");
            }
        }
    }
}

} // renderer_test
<commit_msg>cygwin - disable VK/CUDA (#1777)<commit_after>// render.cpp
#include "renderer-shared.h"
#include "../../source/core/slang-math.h"

#include "d3d11/render-d3d11.h"
#include "d3d12/render-d3d12.h"
#include "open-gl/render-gl.h"
#include "vulkan/render-vk.h"
#include "cuda/render-cuda.h"
#include "cpu/render-cpu.h"
#include <cstring>

namespace gfx {
using namespace Slang;

static const IResource::DescBase s_emptyDescBase = {};

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Global Renderer Functions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

static const uint8_t s_formatSize[] = {
    0, // Unknown,

    uint8_t(sizeof(float) * 4), // RGBA_Float32,
    uint8_t(sizeof(float) * 3), // RGB_Float32,
    uint8_t(sizeof(float) * 2), // RG_Float32,
    uint8_t(sizeof(float) * 1), // R_Float32,

    uint8_t(sizeof(uint32_t)), // RGBA_Unorm_UInt8,
    uint8_t(sizeof(uint32_t)), // BGRA_Unorm_UInt8,

    uint8_t(sizeof(uint16_t)), // R_UInt16,
    uint8_t(sizeof(uint32_t)), // R_UInt32,

    uint8_t(sizeof(float)), // D_Float32,
    uint8_t(sizeof(uint32_t)), // D_Unorm24_S8,
};

static void _compileTimeAsserts()
{
    SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(s_formatSize) == int(Format::CountOf));
}

extern "C"
{
    size_t SLANG_MCALL gfxGetFormatSize(Format format)
    {
        return s_formatSize[int(format)];
    }

    SLANG_GFX_API SlangResult SLANG_MCALL
        gfxCreateDevice(const IDevice::Desc* desc, IDevice** outDevice)
    {
        switch (desc->deviceType)
        {
#if SLANG_WINDOWS_FAMILY
        case DeviceType::DirectX11:
            {
                return createD3D11Device(desc, outDevice);
            }
        case DeviceType::DirectX12:
            {
                return createD3D12Device(desc, outDevice);
            }
        case DeviceType::OpenGl:
            {
                return createGLDevice(desc, outDevice);
            }
        case DeviceType::Vulkan:
            {
                return createVKDevice(desc, outDevice);
            }
        case DeviceType::CUDA:
            {
                return createCUDADevice(desc, outDevice);
            }
        case DeviceType::Default:
            {
                IDevice::Desc newDesc = *desc;
                newDesc.deviceType = DeviceType::DirectX12;
                if (gfxCreateDevice(&newDesc, outDevice) == SLANG_OK)
                    return SLANG_OK;
                newDesc.deviceType = DeviceType::Vulkan;
                if (gfxCreateDevice(&newDesc, outDevice) == SLANG_OK)
                    return SLANG_OK;
                newDesc.deviceType = DeviceType::DirectX11;
                if (gfxCreateDevice(&newDesc, outDevice) == SLANG_OK)
                    return SLANG_OK;
                newDesc.deviceType = DeviceType::OpenGl;
                if (gfxCreateDevice(&newDesc, outDevice) == SLANG_OK)
                    return SLANG_OK;
                return SLANG_FAIL;
            }
            break;
#elif SLANG_LINUX_FAMILY && !defined(__CYGWIN__)
        case DeviceType::Default:
        case DeviceType::Vulkan:
        {
            return createVKDevice(desc, outDevice);
        }
        case DeviceType::CUDA:
        {
            return createCUDADevice(desc, outDevice);
        }
#endif
        case DeviceType::CPU:
            {
                return createCPUDevice(desc, outDevice);
            }
            break;

        default:
            return SLANG_FAIL;
        }
    }

    const char* SLANG_MCALL gfxGetDeviceTypeName(DeviceType type)
    {
        switch (type)
        {
        case gfx::DeviceType::Unknown:
            return "Unknown";
        case gfx::DeviceType::Default:
            return "Default";
        case gfx::DeviceType::DirectX11:
            return "DirectX11";
        case gfx::DeviceType::DirectX12:
            return "DirectX12";
        case gfx::DeviceType::OpenGl:
            return "OpenGL";
        case gfx::DeviceType::Vulkan:
            return "Vulkan";
        case gfx::DeviceType::CPU:
            return "CPU";
        case gfx::DeviceType::CUDA:
            return "CUDA";
        default:
            return "?";
        }
    }

    void SLANG_MCALL gfxGetIdentityProjection(ProjectionStyle style, float projMatrix[16])
    {
        switch (style)
        {
        case ProjectionStyle::DirectX:
        case ProjectionStyle::OpenGl:
            {
                static const float kIdentity[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
                ::memcpy(projMatrix, kIdentity, sizeof(kIdentity));
                break;
            }
        case ProjectionStyle::Vulkan:
            {
                static const float kIdentity[] = {1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
                ::memcpy(projMatrix, kIdentity, sizeof(kIdentity));
                break;
            }
        default:
            {
                assert(!"Not handled");
            }
        }
    }
}

} // renderer_test
<|endoftext|>


<commit_before>#include <QMessageBox>
#include <QDebug>
#include <QHBoxLayout>
#include <QColorDialog>

#include "QColorCombo"

QColorCombo::QColorCombo(QWidget* parent) :
  QFrame(parent), m_combo(NULL),
  m_colorName("#000000"), m_color("#00000") {
  setFrameShape(QFrame::StyledPanel);

  QHBoxLayout* hbox = NULL;
  try {
    hbox = new QHBoxLayout(this);
  }

  catch (std::bad_alloc& ex) {
    qCritical() << "QColorCombo::QColorCombo: "
		<< "Caught std::bad_alloc when trying to create "
		<< "new QHBoxLayout: " << ex.what();
    QMessageBox::critical(this, tr("Fatal error!"),
			  tr("Unable to allocate memory for new QHBoxLayout!"),
			  QMessageBox::Ok, QMessageBox::Ok);
    exit(1);
  }

  try {
    m_combo = new QComboBox(this);

    m_combo->setEditable(false);
  }

  catch (std::bad_alloc& ex) {
    qCritical() << "QColorCombo::QColorCombo: "
		<< "Caught std::bad_alloc when trying to create "
		<< "new QComboBox: " << ex.what();
    QMessageBox::critical(this, tr("Fatal error!"),
			  tr("Unable to allocate memory for new QComboBox!"),
			  QMessageBox::Ok, QMessageBox::Ok);
    exit(1);
  }

  m_combo->addItem(tr("Custom color..."));

  // add default colors to the combo box
  QStringList colorList;
  colorList << "#000000" << "#FFFFFF" << "#808080" << "#800000"
	    << "#804040" << "#FF8080" << "#FF0000" << "#FFFF80"
	    << "#FFFF00" << "#FF8040" << "#FF8000" << "#80FF80"
	    << "#80FF00" << "#00FF00" << "#80FFFF" << "#00FFFF"
	    << "#004080" << "#0000FF" << "#0080FF" << "#0080C0";
  for (QStringList::iterator i=colorList.begin(); i!=colorList.end(); ++i) {
    QString colorName = (*i);
    m_combo->addItem(createIcon(colorName), colorName, QColor(colorName));
  }

  m_combo->setCurrentIndex(1);
  QObject::connect(m_combo, SIGNAL(currentIndexChanged(int)),
		   this, SLOT(combo_currentIndexChanged(int)));

  hbox->addWidget(m_combo);

  setLayout(hbox);
}

/// \brief Create icon for a given color
///
/// Creates a 32x32 pixel icon for the given color name.
///
/// \param color Color name in the form of '#RRGGBB'
QIcon QColorCombo::createIcon(QString color) {
  QPixmap p(32, 32);

  p.fill(QColor(color));

  return QIcon(p);
}

/// \brief Handler for combo box selection changes
///
/// This gets executed when the user selects a new color from our
/// combo box. If the user selects the option to use a custom color
/// we show them a QColorDialog and add the custom color to the top
/// of our color list afterwards.
///
/// \param index Index of the currently selected color in m_combo
void QColorCombo::combo_currentIndexChanged(int index) {
  if (index == 0) {
    // custom color option
    m_color = QColorDialog::getColor(m_color, this);
    m_colorName = m_color.name();
  } else {
    m_colorName = m_combo->itemText(index);
    m_color = m_combo->itemData(index).value<QColor>();
  }

  emit colorChanged(m_colorName);
  emit colorChanged(m_color);
}

/// \brief Add color to m_combo
void QColorCombo::addColor(QColor color) {
  int index = m_combo->findData(color);

  if (index == -1) {
    // color doesn't exist in our dropdown list; create new entry
    QString colorName = color.name().toUpper();
    m_combo->insertItem(1, createIcon(colorName), colorName, color);
    m_combo->setCurrentIndex(1);
  } else {
    // color already exists in our dropdown list
    m_combo->setCurrentIndex(index);
  }
}

/// \brief Add color to m_combo
void QColorCombo::addColor(QString colorName) {
  colorName = colorName.toUpper();

  int index = m_combo->findText(colorName);

  if (index == -1) {
    // color doesn't exist in our dropdown list; create new entry
    m_combo->insertItem(1, createIcon(colorName), colorName, QColor(colorName));
    m_combo->setCurrentIndex(1);
  } else {
    // color already exists in our dropdown list
    m_combo->setCurrentIndex(index);
  }
}

/// \brief Get name of currently selected color
QString QColorCombo::getColorName() {
  return m_colorName;
}

/// \brief Set currently selected color
void QColorCombo::setColorName(QString colorName) {
  if (!colorName.isEmpty()) {
    if (QColor(colorName).isValid()) {
      m_colorName = colorName;
      m_color = QColor(colorName);
      addColor(colorName);
    }
  }
}

/// \brief Get currently selected color
QColor QColorCombo::getColor() {
  return m_color;
}

/// \brief Set currently selected color
void QColorCombo::setColor(QColor color) {
  if (color.isValid()) {
    m_colorName = color.name();
    m_color = color;
    addColor(color);
  }
}

<commit_msg>Add custom colors to dropdown list.<commit_after>#include <QMessageBox>
#include <QDebug>
#include <QHBoxLayout>
#include <QColorDialog>

#include "QColorCombo"

QColorCombo::QColorCombo(QWidget* parent) :
  QFrame(parent), m_combo(NULL),
  m_colorName("#000000"), m_color("#00000") {
  setFrameShape(QFrame::StyledPanel);

  QHBoxLayout* hbox = NULL;
  try {
    hbox = new QHBoxLayout(this);
  }

  catch (std::bad_alloc& ex) {
    qCritical() << "QColorCombo::QColorCombo: "
		<< "Caught std::bad_alloc when trying to create "
		<< "new QHBoxLayout: " << ex.what();
    QMessageBox::critical(this, tr("Fatal error!"),
			  tr("Unable to allocate memory for new QHBoxLayout!"),
			  QMessageBox::Ok, QMessageBox::Ok);
    exit(1);
  }

  try {
    m_combo = new QComboBox(this);

    m_combo->setEditable(false);
  }

  catch (std::bad_alloc& ex) {
    qCritical() << "QColorCombo::QColorCombo: "
		<< "Caught std::bad_alloc when trying to create "
		<< "new QComboBox: " << ex.what();
    QMessageBox::critical(this, tr("Fatal error!"),
			  tr("Unable to allocate memory for new QComboBox!"),
			  QMessageBox::Ok, QMessageBox::Ok);
    exit(1);
  }

  m_combo->addItem(tr("Custom color..."));

  // add default colors to the combo box
  QStringList colorList;
  colorList << "#000000" << "#FFFFFF" << "#808080" << "#800000"
	    << "#804040" << "#FF8080" << "#FF0000" << "#FFFF80"
	    << "#FFFF00" << "#FF8040" << "#FF8000" << "#80FF80"
	    << "#80FF00" << "#00FF00" << "#80FFFF" << "#00FFFF"
	    << "#004080" << "#0000FF" << "#0080FF" << "#0080C0";
  for (QStringList::iterator i=colorList.begin(); i!=colorList.end(); ++i) {
    QString colorName = (*i);
    m_combo->addItem(createIcon(colorName), colorName, QColor(colorName));
  }

  m_combo->setCurrentIndex(1);
  QObject::connect(m_combo, SIGNAL(currentIndexChanged(int)),
		   this, SLOT(combo_currentIndexChanged(int)));

  hbox->addWidget(m_combo);

  setLayout(hbox);
}

/// \brief Create icon for a given color
///
/// Creates a 32x32 pixel icon for the given color name.
///
/// \param color Color name in the form of '#RRGGBB'
QIcon QColorCombo::createIcon(QString color) {
  QPixmap p(32, 32);

  p.fill(QColor(color));

  return QIcon(p);
}

/// \brief Handler for combo box selection changes
///
/// This gets executed when the user selects a new color from our
/// combo box. If the user selects the option to use a custom color
/// we show them a QColorDialog and add the custom color to the top
/// of our color list afterwards.
///
/// \param index Index of the currently selected color in m_combo
void QColorCombo::combo_currentIndexChanged(int index) {
  if (index == 0) {
    // custom color option
    m_color = QColorDialog::getColor(m_color, this);
    m_colorName = m_color.name();
    addColor(m_color);
  } else {
    m_colorName = m_combo->itemText(index);
    m_color = m_combo->itemData(index).value<QColor>();
  }

  emit colorChanged(m_colorName);
  emit colorChanged(m_color);
}

/// \brief Add color to m_combo
void QColorCombo::addColor(QColor color) {
  int index = m_combo->findData(color);

  if (index == -1) {
    // color doesn't exist in our dropdown list; create new entry
    QString colorName = color.name().toUpper();
    m_combo->insertItem(1, createIcon(colorName), colorName, color);
    m_combo->setCurrentIndex(1);
  } else {
    // color already exists in our dropdown list
    m_combo->setCurrentIndex(index);
  }
}

/// \brief Add color to m_combo
void QColorCombo::addColor(QString colorName) {
  colorName = colorName.toUpper();

  int index = m_combo->findText(colorName);

  if (index == -1) {
    // color doesn't exist in our dropdown list; create new entry
    m_combo->insertItem(1, createIcon(colorName), colorName, QColor(colorName));
    m_combo->setCurrentIndex(1);
  } else {
    // color already exists in our dropdown list
    m_combo->setCurrentIndex(index);
  }
}

/// \brief Get name of currently selected color
QString QColorCombo::getColorName() {
  return m_colorName;
}

/// \brief Set currently selected color
void QColorCombo::setColorName(QString colorName) {
  if (!colorName.isEmpty()) {
    if (QColor(colorName).isValid()) {
      m_colorName = colorName;
      m_color = QColor(colorName);
      addColor(colorName);
    }
  }
}

/// \brief Get currently selected color
QColor QColorCombo::getColor() {
  return m_color;
}

/// \brief Set currently selected color
void QColorCombo::setColor(QColor color) {
  if (color.isValid()) {
    m_colorName = color.name();
    m_color = color;
    addColor(color);
  }
}

<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2011 SCHUTZ Sacha
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "qjsonmodel.h"
#include <QFile>
#include <QDebug>
#include <QFont>

QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent)
{
    mParent = parent;
}

QJsonTreeItem::~QJsonTreeItem()
{
    qDeleteAll(mChilds);
}

void QJsonTreeItem::appendChild(QJsonTreeItem *item)
{
    mChilds.append(item);
}

QJsonTreeItem *QJsonTreeItem::child(int row)
{
    return mChilds.value(row);
}

QJsonTreeItem *QJsonTreeItem::parent()
{
    return mParent;
}

int QJsonTreeItem::childCount() const
{
    return mChilds.count();
}

int QJsonTreeItem::row() const
{
    if (mParent)
        return mParent->mChilds.indexOf(const_cast<QJsonTreeItem*>(this));

    return 0;
}

void QJsonTreeItem::setKey(const QString &key)
{
    mKey = key;
}

void QJsonTreeItem::setValue(const QString &value)
{
    mValue = value;
}

void QJsonTreeItem::setType(const QJsonValue::Type &type)
{
    mType = type;
}

QString QJsonTreeItem::key() const
{
    return mKey;
}

QString QJsonTreeItem::value() const
{
    return mValue;
}

QJsonValue::Type QJsonTreeItem::type() const
{
    return mType;
}

QJsonTreeItem* QJsonTreeItem::load(const QJsonValue& value, QJsonTreeItem* parent)
{
    QJsonTreeItem * rootItem = new QJsonTreeItem(parent);
    rootItem->setKey("root");

    if ( value.isObject())
    {

        //Get all QJsonValue childs
        for (QString key : value.toObject().keys()){
            QJsonValue v = value.toObject().value(key);
            QJsonTreeItem * child = load(v,rootItem);
            child->setKey(key);
            child->setType(v.type());
            rootItem->appendChild(child);

        }

    }

    else if ( value.isArray())
    {
        //Get all QJsonValue childs
        int index = 0;
        for (QJsonValue v : value.toArray()){

            QJsonTreeItem * child = load(v,rootItem);
            child->setKey(QString::number(index));
            child->setType(v.type());
            rootItem->appendChild(child);
            ++index;
        }
    }
    else
    {
        rootItem->setValue(value.toVariant().toString());
        rootItem->setType(value.type());
    }

    return rootItem;
}

//=========================================================================

QJsonModel::QJsonModel(QObject *parent) :
    QAbstractItemModel(parent)
{
    mRootItem = new QJsonTreeItem;
    mHeaders.append("key");
    mHeaders.append("value");

}

QJsonModel::~QJsonModel()
{
    delete mRootItem;
}

bool QJsonModel::load(const QString &fileName)
{
    QFile file(fileName);
    bool success = false;
    if (file.open(QIODevice::ReadOnly)) {
        success = load(&file);
        file.close();
    }
    else success = false;

    return success;
}

bool QJsonModel::load(QIODevice *device)
{
    return loadJson(device->readAll());
}

bool QJsonModel::loadJson(const QByteArray &json)
{
    auto const& jdoc = QJsonDocument::fromJson(json);

    if (!jdoc.isNull())
    {
        beginResetModel();
        delete mRootItem;
        if (jdoc.isArray()) {
            mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.array()));
            mRootItem->setType(QJsonValue::Array);

        } else {
            mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.object()));
            mRootItem->setType(QJsonValue::Object);
        }
        endResetModel();
        return true;
    }

    qDebug()<<Q_FUNC_INFO<<"cannot load json";
    return false;
}

QVariant QJsonModel::data(const QModelIndex &index, int role) const
{

    if (!index.isValid())
        return QVariant();

    QJsonTreeItem *item = static_cast<QJsonTreeItem*>(index.internalPointer());

    if (role == Qt::DisplayRole) {

        if (index.column() == 0)
            return QString("%1").arg(item->key());

        if (index.column() == 1)
            return QString("%1").arg(item->value());
    } else if (Qt::EditRole == role) {
        if (index.column() == 1) {
            return QString("%1").arg(item->value());
        }
    }

    return QVariant();

}

bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    int col = index.column();
    if (Qt::EditRole == role) {
        if (col == 1) {
            QJsonTreeItem *item = static_cast<QJsonTreeItem*>(index.internalPointer());
                item->setValue(value.toString());
                emit dataChanged(index, index, {Qt::EditRole});
                return true;
        }
    }

    return false;
}

QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal) {

        return mHeaders.value(section);
    }
    else
        return QVariant();
}

QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    QJsonTreeItem *parentItem;

    if (!parent.isValid())
        parentItem = mRootItem;
    else
        parentItem = static_cast<QJsonTreeItem*>(parent.internalPointer());

    QJsonTreeItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QModelIndex QJsonModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    QJsonTreeItem *childItem = static_cast<QJsonTreeItem*>(index.internalPointer());
    QJsonTreeItem *parentItem = childItem->parent();

    if (parentItem == mRootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

int QJsonModel::rowCount(const QModelIndex &parent) const
{
    QJsonTreeItem *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = mRootItem;
    else
        parentItem = static_cast<QJsonTreeItem*>(parent.internalPointer());

    return parentItem->childCount();
}

int QJsonModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return 2;
}

Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const
{
    int col = index.column();
    if (col == 1) {
        return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
    } else {
        return QAbstractItemModel::flags(index);
    }
}

QJsonDocument QJsonModel::json() const
{

    auto v = genJson(mRootItem);
    QJsonDocument doc;

    if (v.isObject()) {
        doc = QJsonDocument(v.toObject());
    } else {
        doc = QJsonDocument(v.toArray());
    }

    return doc;
}

QJsonValue  QJsonModel::genJson(QJsonTreeItem * item) const
{
    auto type   = item->type();
    int  nchild = item->childCount();

    if (QJsonValue::Object == type) {
        QJsonObject jo;
        for (int i = 0; i < nchild; ++i) {
            auto ch = item->child(i);
            auto key = ch->key();
            jo.insert(key, genJson(ch));
        }
        return  jo;
    } else if (QJsonValue::Array == type) {
        QJsonArray arr;
        for (int i = 0; i < nchild; ++i) {
            auto ch = item->child(i);
            arr.append(genJson(ch));
        }
        return arr;
    } else {
        QJsonValue va(item->value());
        return va;
    }

}
<commit_msg>Fix: Root TreeItem (Object and  Array) are not editable<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2011 SCHUTZ Sacha
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "qjsonmodel.h"
#include <QFile>
#include <QDebug>
#include <QFont>

QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent)
{
    mParent = parent;
}

QJsonTreeItem::~QJsonTreeItem()
{
    qDeleteAll(mChilds);
}

void QJsonTreeItem::appendChild(QJsonTreeItem *item)
{
    mChilds.append(item);
}

QJsonTreeItem *QJsonTreeItem::child(int row)
{
    return mChilds.value(row);
}

QJsonTreeItem *QJsonTreeItem::parent()
{
    return mParent;
}

int QJsonTreeItem::childCount() const
{
    return mChilds.count();
}

int QJsonTreeItem::row() const
{
    if (mParent)
        return mParent->mChilds.indexOf(const_cast<QJsonTreeItem*>(this));

    return 0;
}

void QJsonTreeItem::setKey(const QString &key)
{
    mKey = key;
}

void QJsonTreeItem::setValue(const QString &value)
{
    mValue = value;
}

void QJsonTreeItem::setType(const QJsonValue::Type &type)
{
    mType = type;
}

QString QJsonTreeItem::key() const
{
    return mKey;
}

QString QJsonTreeItem::value() const
{
    return mValue;
}

QJsonValue::Type QJsonTreeItem::type() const
{
    return mType;
}

QJsonTreeItem* QJsonTreeItem::load(const QJsonValue& value, QJsonTreeItem* parent)
{
    QJsonTreeItem * rootItem = new QJsonTreeItem(parent);
    rootItem->setKey("root");

    if ( value.isObject())
    {

        //Get all QJsonValue childs
        for (QString key : value.toObject().keys()){
            QJsonValue v = value.toObject().value(key);
            QJsonTreeItem * child = load(v,rootItem);
            child->setKey(key);
            child->setType(v.type());
            rootItem->appendChild(child);

        }

    }

    else if ( value.isArray())
    {
        //Get all QJsonValue childs
        int index = 0;
        for (QJsonValue v : value.toArray()){

            QJsonTreeItem * child = load(v,rootItem);
            child->setKey(QString::number(index));
            child->setType(v.type());
            rootItem->appendChild(child);
            ++index;
        }
    }
    else
    {
        rootItem->setValue(value.toVariant().toString());
        rootItem->setType(value.type());
    }

    return rootItem;
}

//=========================================================================

QJsonModel::QJsonModel(QObject *parent) :
    QAbstractItemModel(parent)
{
    mRootItem = new QJsonTreeItem;
    mHeaders.append("key");
    mHeaders.append("value");

}

QJsonModel::~QJsonModel()
{
    delete mRootItem;
}

bool QJsonModel::load(const QString &fileName)
{
    QFile file(fileName);
    bool success = false;
    if (file.open(QIODevice::ReadOnly)) {
        success = load(&file);
        file.close();
    }
    else success = false;

    return success;
}

bool QJsonModel::load(QIODevice *device)
{
    return loadJson(device->readAll());
}

bool QJsonModel::loadJson(const QByteArray &json)
{
    auto const& jdoc = QJsonDocument::fromJson(json);

    if (!jdoc.isNull())
    {
        beginResetModel();
        delete mRootItem;
        if (jdoc.isArray()) {
            mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.array()));
            mRootItem->setType(QJsonValue::Array);

        } else {
            mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.object()));
            mRootItem->setType(QJsonValue::Object);
        }
        endResetModel();
        return true;
    }

    qDebug()<<Q_FUNC_INFO<<"cannot load json";
    return false;
}

QVariant QJsonModel::data(const QModelIndex &index, int role) const
{

    if (!index.isValid())
        return QVariant();

    QJsonTreeItem *item = static_cast<QJsonTreeItem*>(index.internalPointer());

    if (role == Qt::DisplayRole) {

        if (index.column() == 0)
            return QString("%1").arg(item->key());

        if (index.column() == 1)
            return QString("%1").arg(item->value());
    } else if (Qt::EditRole == role) {
        if (index.column() == 1) {
            return QString("%1").arg(item->value());
        }
    }

    return QVariant();

}

bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    int col = index.column();
    if (Qt::EditRole == role) {
        if (col == 1) {
            QJsonTreeItem *item = static_cast<QJsonTreeItem*>(index.internalPointer());
                item->setValue(value.toString());
                emit dataChanged(index, index, {Qt::EditRole});
                return true;
        }
    }

    return false;
}

QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal) {

        return mHeaders.value(section);
    }
    else
        return QVariant();
}

QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    QJsonTreeItem *parentItem;

    if (!parent.isValid())
        parentItem = mRootItem;
    else
        parentItem = static_cast<QJsonTreeItem*>(parent.internalPointer());

    QJsonTreeItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QModelIndex QJsonModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    QJsonTreeItem *childItem = static_cast<QJsonTreeItem*>(index.internalPointer());
    QJsonTreeItem *parentItem = childItem->parent();

    if (parentItem == mRootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

int QJsonModel::rowCount(const QModelIndex &parent) const
{
    QJsonTreeItem *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = mRootItem;
    else
        parentItem = static_cast<QJsonTreeItem*>(parent.internalPointer());

    return parentItem->childCount();
}

int QJsonModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return 2;
}

Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const
{
    int col   = index.column();
    auto item = static_cast<QJsonTreeItem*>(index.internalPointer());

    auto isArray = QJsonValue::Array == item->type();
    auto isObject = QJsonValue::Object == item->type();

    if ((col == 1) && !(isArray || isObject)) {
        return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
    } else {
        return QAbstractItemModel::flags(index);
    }
}

QJsonDocument QJsonModel::json() const
{

    auto v = genJson(mRootItem);
    QJsonDocument doc;

    if (v.isObject()) {
        doc = QJsonDocument(v.toObject());
    } else {
        doc = QJsonDocument(v.toArray());
    }

    return doc;
}

QJsonValue  QJsonModel::genJson(QJsonTreeItem * item) const
{
    auto type   = item->type();
    int  nchild = item->childCount();

    if (QJsonValue::Object == type) {
        QJsonObject jo;
        for (int i = 0; i < nchild; ++i) {
            auto ch = item->child(i);
            auto key = ch->key();
            jo.insert(key, genJson(ch));
        }
        return  jo;
    } else if (QJsonValue::Array == type) {
        QJsonArray arr;
        for (int i = 0; i < nchild; ++i) {
            auto ch = item->child(i);
            arr.append(genJson(ch));
        }
        return arr;
    } else {
        QJsonValue va(item->value());
        return va;
    }

}
<|endoftext|>


<commit_before>/*
Copyright (c) 2012, Ronie Martinez
ronmarti18@gmail.com
All rights reserved.

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

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

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

#include "qpsdplugin.h"
#include <QRgb>
#include <QColor>

qpsdPlugn::qpsdPlugn(QObject *parent) :
    QImageIOPlugin(parent)
{
}

qpsdPlugn::~qpsdPlugn()
{

}

QStringList qpsdPlugn::keys() const
{
    return QStringList() << "psd";//TODO: add PSB (Photoshop Big) support
}

QImageIOPlugin::Capabilities qpsdPlugn::capabilities(
    QIODevice *device, const QByteArray &format) const
{
    if (format == "psd")
        return Capabilities(CanRead);//TODO: add CanWrite support
    if (!(format.isEmpty() && device->isOpen()))
        return 0;

    Capabilities cap;
    if (device->isReadable() && qpsdHandler::canRead(device))
        cap |= CanRead;
   // if (device->isWritable())
   //     cap |= CanWrite;
    return cap;
}

QImageIOHandler *qpsdPlugn::create(
    QIODevice *device, const QByteArray &format) const
{
    QImageIOHandler *handler = new qpsdHandler;
    handler->setDevice(device);
    handler->setFormat(format);
    return handler;
}

//Q_EXPORT_STATIC_PLUGIN(qpsdPlugn)
Q_EXPORT_PLUGIN2(qpsd, qpsdPlugn)

qpsdHandler::qpsdHandler()
{

}

qpsdHandler::~qpsdHandler()
{

}

bool qpsdHandler::canRead() const
{
    if (canRead(device())) {
        setFormat("psd");
        return true;
    }
    return false;
}

bool qpsdHandler::canRead(QIODevice *device)
{
    return device->peek(4) == QByteArray("\x38\x42\x50\x53"); //8BPS
}

bool qpsdHandler::read(QImage *image)
{
    QDataStream input(device());
    quint32 signature, height, width, colorModeDataLength, imageResourcesLength, layerAndMaskInformationLength;
    quint16 version, channels, depth, colorMode, compression;
    QByteArray colorData;
    input.setByteOrder(QDataStream::BigEndian);
    input >> signature >> version ;
    input.skipRawData(6);//reserved bytes should be 6-byte in size
    input >> channels >> height >> width >> depth >> colorMode;
    input >> colorModeDataLength;
    if(colorModeDataLength != 0)
    {
        quint8 byte;
        for(quint32 i=0; i<colorModeDataLength; ++i)
        {
            input >> byte;
            colorData.append(byte);
        }
    }
    input >> imageResourcesLength;
    input.skipRawData(imageResourcesLength);
    input >> layerAndMaskInformationLength;
    input.skipRawData(layerAndMaskInformationLength);
    input >> compression;

    if (input.status() != QDataStream::Ok || signature != 0x38425053 || version != 0x0001)
        return false;
    QByteArray decompressed;
    switch(compression)
    {
    case 0: /*RAW IMAGE DATA - UNIMPLEMENTED*/
        break;
    case 1: /*RLE COMPRESSED DATA*/
        // The RLE-compressed data is proceeded by a 2-byte data count for each row in the data,
        // which we're going to just skip.
        input.skipRawData(height*channels*2);

        quint8 byte,count;
        decompressed.clear();

        /*Code based on PackBits implementation which is primarily used by Photoshop for RLE encoding/decoding*/
        while(!input.atEnd())
        {
            input >> byte;
            if(byte > 128)
            {
                count=256-byte;
                input >>  byte;
                for(quint8 i=0;i<=count;i++)
                {
                    decompressed.append(byte);

                }
            }
            else if(byte < 128)
            {
                count=byte+1;
                for(quint8 i=0;i<count;i++)
                {
                    input >> byte;
                    decompressed.append(byte);
                }
            }
        }
        break;
    case 2:/*ZIP WITHOUT PREDICTION - UNIMPLEMENTED*/
        break;
    case 3:/*ZIP WITH PREDICTION - UNIMPLEMENTED*/
        break;
    }

    int totalBytes = width * height;
    if(decompressed.size() != channels * totalBytes) //used "channels" instead of only "3"
        return false;

    switch(colorMode)
    {
    case 0: /*BITMAP - UNIMPLEMENTED*/
        break;
    case 1: /*GRAYSCALE - FOR TESTING*/
        switch(depth)
        {
        case 8:
            switch(channels)
            {
            case 1:
                //TODO: verify code with other GRAYSCALE PSD files
                //Though it is working! Isn't it odd?
                //most guides from Qt threads says about QImage::Format_Indexed8
                //but I guess it is not ideal
//                QImage result(width, height, QImage::Format_RGB32);
//                const char *data = decompressed.constData();
//                QRgb  *p, *end;
//                for (quint32 y = 0; y < height; ++y) {
//                    p = (QRgb *)result.scanLine(y);
//                    end = p + width;
//                    while (p < end) {
//                        *p++ = qRgb(data[0], data[0],data[0]);
//                        ++data;
//                    }
//                }

                QImage result(width, height, QImage::Format_Indexed8);
                int index = 0;
                const int IndexCount = 256;
                while(index < IndexCount){
                    result.setColor(index, qRgb(index, index, index));
                    ++index;
                }

                const char *data = decompressed.constData();
                for(quint32 i=0; i < height; ++i)
                {
                    for(quint32 j=0; j < width; ++j)
                    {
                        result.setPixel(j,i,(quint8)data[0]);
                        ++data;
                    }
                }

                *image = result;
                break;
            }
        }

        break;
    case 2: /*INDEXED*/
        switch(depth)
        {
        case 8:
            switch(channels)
            {
            case 1:
                QImage result(width, height, QImage::Format_Indexed8);

                const char *colorTable = colorData.constData();
                int index = 0;
                int indexCount = colorData.size() / 3;
                Q_ASSERT(indexCount == 256);
                while(index < indexCount){
                    /*
                     * reference https://github.com/OpenImageIO/oiio/blob/master/src/psd.imageio/psdinput.cpp
                     * function bool PSDInput::indexed_to_rgb (char *dst)
                     */
                    result.setColor(index++,
                                    qRgb(colorTable[0], colorTable[256], colorTable[512]));
                    ++colorTable;
                }

                const char *data = decompressed.constData();
                for(quint32 i=0; i < height; ++i)
                {
                    for(quint32 j=0; j < width; ++j)
                    {
                        result.setPixel(j,i,(quint8)data[0]);
                        ++data;
                    }
                }
                *image=result;
                break;
            }
        }
        break;
    case 3: /*RGB*/
        switch(depth)
        {
        case 1:
            break;
        case 8:
            switch(channels)
            {
            case 1:
                break;
            case 3:
                {
                    QImage result(width, height, QImage::Format_RGB32);
                    const char *data = decompressed.constData();
                    QRgb  *p, *end;
                    for (quint32 y = 0; y < height; ++y) {
                        p = (QRgb *)result.scanLine(y);
                        end = p + width;
                        while (p < end) {
                            *p++ = qRgb(data[0], data[totalBytes], data[totalBytes + totalBytes]);
                            ++data;
                        }
                    }

                    *image = result;
                }
                break;
            case 4:
                {
                    QImage result(width, height, QImage::Format_ARGB32);
                    const char *data = decompressed.constData();
                    QRgb  *p, *end;
                    for (quint32 y = 0; y < height; ++y) {
                        p = (QRgb *)result.scanLine(y);
                        end = p + width;
                        while (p < end) {
                            *p++ = qRgba(data[0], data[totalBytes],
                                     data[totalBytes + totalBytes],
                                     data[totalBytes + totalBytes + totalBytes]);
                            ++data;
                        }
                    }

                    *image = result;
                }
                break;
            }

            break;
        case 16:
            break;
        }
        break;
    case 4: /*CMYK*/
        switch(depth)
        {
        case 8:
            switch(channels)
            {
            case 4:
                QImage result(width, height, QImage::Format_RGB32);
                const char *data = decompressed.constData();
                QRgb  *p, *end;
                quint8 cyan, magenta, yellow, key;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        cyan = data[0];
                        magenta = data[totalBytes];
                        yellow = data[totalBytes + totalBytes];
                        key = data[totalBytes + totalBytes + totalBytes];
                        *p++ = QColor::fromCmyk(255-cyan, 255-magenta,255-yellow, 255-key).rgb();
                        ++data;
                    }
                }
                *image = result;
                break;
            }
        }
        break;
    case 7: /*MULTICHANNEL - UNIMPLEMENTED*/
        break;
    case 8: /*DUOTONE - UNIMPLEMENTED*/
        break;
    case 9: /*LAB - UNIMPLEMENTED*/
        break;
    }

    return input.status() == QDataStream::Ok;
}

bool qpsdHandler::supportsOption(ImageOption option) const
{
    return option == Size;
}

QVariant qpsdHandler::option(ImageOption option) const
{
    if (option == Size) {
        QByteArray bytes = device()->peek(26);
        QDataStream input(bytes);
        quint32 signature, height, width;
        quint16 version, channels, depth, colorMode;
        input.setByteOrder(QDataStream::BigEndian);
        input >> signature >> version ;
        input.skipRawData(6);//reserved bytes should be 6-byte in size
        input >> channels >> height >> width >> depth >> colorMode;
        if (input.status() == QDataStream::Ok && signature == 0x38425053 && version == 0x0001)
            return QSize(width, height);
    }
    return QVariant();
}
<commit_msg>Add: cmyk mode with 5 channels support (seems no work).   Optimized for speed in loop.<commit_after>/*
Copyright (c) 2012, Ronie Martinez
ronmarti18@gmail.com
All rights reserved.

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

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

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

#include "qpsdplugin.h"
#include <QRgb>
#include <QColor>

qpsdPlugn::qpsdPlugn(QObject *parent) :
    QImageIOPlugin(parent)
{
}

qpsdPlugn::~qpsdPlugn()
{

}

QStringList qpsdPlugn::keys() const
{
    return QStringList() << "psd";//TODO: add PSB (Photoshop Big) support
}

QImageIOPlugin::Capabilities qpsdPlugn::capabilities(
    QIODevice *device, const QByteArray &format) const
{
    if (format == "psd")
        return Capabilities(CanRead);//TODO: add CanWrite support
    if (!(format.isEmpty() && device->isOpen()))
        return 0;

    Capabilities cap;
    if (device->isReadable() && qpsdHandler::canRead(device))
        cap |= CanRead;
    // if (device->isWritable())
    //     cap |= CanWrite;
    return cap;
}

QImageIOHandler *qpsdPlugn::create(
    QIODevice *device, const QByteArray &format) const
{
    QImageIOHandler *handler = new qpsdHandler;
    handler->setDevice(device);
    handler->setFormat(format);
    return handler;
}

//Q_EXPORT_STATIC_PLUGIN(qpsdPlugn)
Q_EXPORT_PLUGIN2(qpsd, qpsdPlugn)

qpsdHandler::qpsdHandler()
{

}

qpsdHandler::~qpsdHandler()
{

}

bool qpsdHandler::canRead() const
{
    if (canRead(device())) {
        setFormat("psd");
        return true;
    }
    return false;
}

bool qpsdHandler::canRead(QIODevice *device)
{
    return device->peek(4) == QByteArray("\x38\x42\x50\x53"); //8BPS
}

bool qpsdHandler::read(QImage *image)
{
    QDataStream input(device());
    quint32 signature, height, width, colorModeDataLength, imageResourcesLength, layerAndMaskInformationLength;
    quint16 version, channels, depth, colorMode, compression;
    QByteArray colorData;
    input.setByteOrder(QDataStream::BigEndian);
    input >> signature >> version ;
    input.skipRawData(6);//reserved bytes should be 6-byte in size
    input >> channels >> height >> width >> depth >> colorMode;
    input >> colorModeDataLength;
    if(colorModeDataLength != 0)
    {
        quint8 byte;
        for(quint32 i=0; i<colorModeDataLength; ++i)
        {
            input >> byte;
            colorData.append(byte);
        }
    }
    input >> imageResourcesLength;
    input.skipRawData(imageResourcesLength);
    input >> layerAndMaskInformationLength;
    input.skipRawData(layerAndMaskInformationLength);
    input >> compression;

    if (input.status() != QDataStream::Ok || signature != 0x38425053 || version != 0x0001)
        return false;

    QByteArray decompressed;
    switch(compression)
    {
    case 0: /*RAW IMAGE DATA - UNIMPLEMENTED*/
        break;
    case 1: /*RLE COMPRESSED DATA*/
        // The RLE-compressed data is proceeded by a 2-byte data count for each row in the data,
        // which we're going to just skip.
        input.skipRawData(height*channels*2);

        quint8 byte,count;
        decompressed.clear();

        /*Code based on PackBits implementation which is primarily used by Photoshop for RLE encoding/decoding*/
        while(!input.atEnd())
        {
            input >> byte;
            if(byte > 128)
            {
                count=256-byte;
                input >>  byte;
                for(quint8 i=0;i<=count;i++)
                {
                    decompressed.append(byte);

                }
            }
            else if(byte < 128)
            {
                count=byte+1;
                for(quint8 i=0;i<count;i++)
                {
                    input >> byte;
                    decompressed.append(byte);
                }
            }
        }
        break;
    case 2:/*ZIP WITHOUT PREDICTION - UNIMPLEMENTED*/
        break;
    case 3:/*ZIP WITH PREDICTION - UNIMPLEMENTED*/
        break;
    }

    int totalBytes = width * height;
    if(decompressed.size() != channels * totalBytes) //used "channels" instead of only "3"
        return false;

    switch(colorMode)
    {
    case 0: /*BITMAP - UNIMPLEMENTED*/
        break;
    case 1: /*GRAYSCALE - FOR TESTING*/
        switch(depth)
        {
        case 8:
            switch(channels)
            {
            case 1:
                QImage result(width, height, QImage::Format_Indexed8);
                const int IndexCount = 256;
                for(int i = 0; i < IndexCount; ++i){
                    result.setColor(i, qRgb(i, i, i));
                }

                quint8 *data = (quint8*)decompressed.constData();
                for(quint32 i=0; i < height; ++i)
                {
                    for(quint32 j=0; j < width; ++j)
                    {
                        result.setPixel(j,i, *data);
                        ++data;
                    }
                }

                *image = result;
                break;
            }
        }

        break;
    case 2: /*INDEXED*/
        switch(depth)
        {
        case 8:
            switch(channels)
            {
            case 1:
                QImage result(width, height, QImage::Format_Indexed8);
                int indexCount = colorData.size() / 3;
                Q_ASSERT(indexCount == 256);
                quint8 *red = (quint8*)colorData.constData();
                quint8 *green = red + indexCount;
                quint8 *blue = green + indexCount;
                for(int i=0; i < indexCount; ++i){
                    /*
                     * reference https://github.com/OpenImageIO/oiio/blob/master/src/psd.imageio/psdinput.cpp
                     * function bool PSDInput::indexed_to_rgb (char *dst)
                     */
                    result.setColor(i, qRgb(*red, *green, *blue));
                    ++red; ++green; ++blue;
                }

                quint8 *data = (quint8*)decompressed.constData();
                for(quint32 i=0; i < height; ++i)
                {
                    for(quint32 j=0; j < width; ++j)
                    {
                        result.setPixel(j,i,*data);
                        ++data;
                    }
                }
                *image=result;
                break;
            }
        }
        break;
    case 3: /*RGB*/
        switch(depth)
        {
        case 1:
            break;
        case 8:
            switch(channels)
            {
            case 1:
                break;
            case 3:
            {
                QImage result(width, height, QImage::Format_RGB32);
                quint8 *red = (quint8*)decompressed.constData();
                quint8 *green = red + totalBytes;
                quint8 *blue = green + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = qRgb(*red, *green, *blue);
                        ++p; ++red; ++green; ++blue;
                    }
                }

                *image = result;
            }
                break;
            case 4:
            {
                QImage result(width, height, QImage::Format_ARGB32);
                quint8 *red = (quint8*)decompressed.constData();
                quint8 *green = red + totalBytes;
                quint8 *blue = green + totalBytes;
                quint8 *alpha = blue + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = qRgba(*red, *green, *blue, *alpha);
                        ++p; ++red; ++green; ++blue; ++alpha;
                    }
                }

                *image = result;
            }
                break;
            case 5:
                qDebug("5 channels of rgb mode");
                return false;
            }

            break;
        case 16:
            break;
        }
        break;
    case 4: /*CMYK*/
        switch(depth)
        {
        case 8:
            switch(channels)
            {
            case 4:
            {
                QImage result(width, height, QImage::Format_RGB32);
                quint8 *cyan = (quint8*)decompressed.constData();
                quint8 *magenta = cyan + totalBytes;
                quint8 *yellow = magenta + totalBytes;
                quint8 *key = yellow + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = QColor::fromCmyk(255-*cyan, 255-*magenta,
                                              255-*yellow, 255-*key).rgb();
                        ++p; ++cyan; ++magenta; ++yellow; ++key;
                    }
                }
                *image = result;
            }
                break;
            case 5:
            {
                QImage result(width, height, QImage::Format_ARGB32);
                quint8 *alpha = (quint8*)decompressed.constData();
                quint8 *cyan = alpha + totalBytes;
                quint8 *magenta = cyan + totalBytes;
                quint8 *yellow = magenta + totalBytes;
                quint8 *key = yellow + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = QColor::fromCmyk(255-*cyan, 255-*magenta,
                                              255-*yellow, 255-*key,
                                              *alpha).rgba();
                        ++p; ++alpha; ++cyan; ++magenta; ++yellow; ++key;
                    }
                }
                *image = result;
            }
                break;
            }
        }
        break;
    case 7: /*MULTICHANNEL - UNIMPLEMENTED*/
        break;
    case 8: /*DUOTONE - UNIMPLEMENTED*/
        break;
    case 9: /*LAB - UNIMPLEMENTED*/
        break;
    }

    return input.status() == QDataStream::Ok;
}

bool qpsdHandler::supportsOption(ImageOption option) const
{
    return option == Size;
}

QVariant qpsdHandler::option(ImageOption option) const
{
    if (option == Size) {
        QByteArray bytes = device()->peek(26);
        QDataStream input(bytes);
        quint32 signature, height, width;
        quint16 version, channels, depth, colorMode;
        input.setByteOrder(QDataStream::BigEndian);
        input >> signature >> version ;
        input.skipRawData(6);//reserved bytes should be 6-byte in size
        input >> channels >> height >> width >> depth >> colorMode;
        if (input.status() == QDataStream::Ok && signature == 0x38425053 && version == 0x0001)
            return QSize(width, height);
    }
    return QVariant();
}
<|endoftext|>


<commit_before>// $Id$

/*
Copyright (c) 2007-2011, Trustees of The Leland Stanford Junior University
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 Stanford University 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.
*/

#ifndef _TRAFFICMANAGER_HPP_
#define _TRAFFICMANAGER_HPP_

#include <list>
#include <map>
#include <set>
#include <cassert>

#include "module.hpp"
#include "config_utils.hpp"
#include "network.hpp"
#include "flit.hpp"
#include "buffer_state.hpp"
#include "stats.hpp"
#include "traffic.hpp"
#include "routefunc.hpp"
#include "outputset.hpp"
#include "injection.hpp"

//register the requests to a node
class PacketReplyInfo;

class TrafficManager : public Module {
protected:
  int _nodes;
  int _routers;

  vector<Network *> _net;
  vector<vector<Router *> > _router;

  // ============ Traffic ============

  int    _classes;

  vector<double> _load;

  vector<int>    _packet_size;

  /*false means all packet types are the same length "const_flits_per_packet"
   *All packets uses all VCS
   *packet types are generated randomly, essentially making it only 1 type
   *of packet in the network
   *
   *True means only request packets are generated and replies are generated
   *as a response to the requests, packets are now difference length, correspond
   *to "read_request_size" etc.
   */
  vector<int> _use_read_write;

  vector<int> _read_request_size;
  vector<int> _read_reply_size;
  vector<int> _write_request_size;
  vector<int> _write_reply_size;

  vector<string> _traffic;

  vector<int> _class_priority;

  map<int, pair<int, vector<int> > > _class_prio_map;

  vector<TrafficPattern *> _traffic_pattern;
  vector<InjectionProcess *> _injection_process;

  // ============ Message priorities ============

  enum ePriority { class_based, age_based, network_age_based, local_age_based, queue_length_based, hop_count_based, sequence_based, none };

  ePriority _pri_type;

  // ============ Injection VC states  ============

  vector<vector<BufferState *> > _buf_states;
  vector<vector<vector<int> > > _last_vc;

  // ============ Routing ============

  tRoutingFunction _rf;

  // ============ Injection queues ============

  vector<vector<int> > _qtime;
  vector<vector<bool> > _qdrained;
  vector<vector<list<Flit *> > > _partial_packets;

  vector<map<int, Flit *> > _total_in_flight_flits;
  vector<map<int, Flit *> > _measured_in_flight_flits;
  vector<map<int, Flit *> > _retired_packets;
  bool _empty_network;

  // ============ physical sub-networks ==========

  int _subnets;

  vector<int> _subnet;

  // ============ deadlock ==========

  int _deadlock_timer;
  int _deadlock_warn_timeout;

  // ============ request & replies ==========================

  vector<int> _sent_packets;
  vector<list<PacketReplyInfo*> > _repliesPending;
  vector<int> _requestsOutstanding;
  bool _replies_inherit_priority;

  // ============ Statistics ============

  vector<Stats *> _plat_stats;
  vector<double> _overall_min_plat;
  vector<double> _overall_avg_plat;
  vector<double> _overall_max_plat;

  vector<Stats *> _tlat_stats;
  vector<double> _overall_min_tlat;
  vector<double> _overall_avg_tlat;
  vector<double> _overall_max_tlat;

  vector<Stats *> _frag_stats;
  vector<double> _overall_min_frag;
  vector<double> _overall_avg_frag;
  vector<double> _overall_max_frag;

  vector<vector<Stats *> > _pair_plat;
  vector<vector<Stats *> > _pair_tlat;

  vector<Stats *> _hop_stats;
  vector<double> _overall_hop_stats;

  vector<vector<int> > _sent_flits;
  vector<double> _overall_min_sent;
  vector<double> _overall_avg_sent;
  vector<double> _overall_max_sent;
  vector<vector<int> > _accepted_flits;
  vector<double> _overall_min_accepted;
  vector<double> _overall_avg_accepted;
  vector<double> _overall_max_accepted;

  vector<int> _slowest_flit;

  map<string, Stats *> _stats;

  // ============ Simulation parameters ============

  enum eSimState { warming_up, running, draining, done };
  eSimState _sim_state;

  bool _measure_latency;

  int   _reset_time;
  int   _end_time;
  int   _drain_time;

  int   _total_sims;
  int   _sample_period;
  int   _max_samples;
  int   _warmup_periods;

  int   _include_queuing;

  vector<int> _measure_stats;

  vector<double> _latency_thres;

  vector<double> _stopping_threshold;
  vector<double> _acc_stopping_threshold;

  vector<double> _warmup_threshold;
  vector<double> _acc_warmup_threshold;

  int _cur_id;
  int _cur_pid;
  int _cur_tid;
  int _time;

  set<int> _flits_to_watch;
  set<int> _packets_to_watch;
  set<int> _transactions_to_watch;

  bool _print_csv_results;
  bool _drain_measured_only;

  //flits to watch
  ostream * _stats_out;

#ifdef TRACK_FLOWS
  ostream * _active_packets_out;
  ostream * _injected_flits_out;
  ostream * _ejected_flits_out;
  ostream * _received_flits_out;
  ostream * _sent_flits_out;
  ostream * _stored_flits_out;
#endif

  // ============ Internal methods ============
protected:

  virtual void _RetireFlit( Flit *f, int dest );

  void _Inject();
  void _Step( );

  bool _PacketsOutstanding( ) const;

  virtual int  _IssuePacket( int source, int cl );
  void _GeneratePacket( int source, int size, int cl, int time );

  virtual void _ClearStats( );

  void _ComputeStats( const vector<int> & stats, int *sum, int *min = NULL, int *max = NULL, int *min_pos = NULL, int *max_pos = NULL ) const;

  virtual bool _SingleSim( );

  void _DisplayRemaining( ostream & os = cout ) const;

  void _LoadWatchList(const string & filename);

  virtual void _UpdateOverallStats();

  virtual string _OverallStatsCSV(int c = 0) const;

public:

  static TrafficManager * NewTrafficManager(Configuration const & config,
					    vector<Network *> const & net);

  TrafficManager( const Configuration &config, const vector<Network *> & net );
  virtual ~TrafficManager( );

  bool Run( );

  virtual void WriteStats( ostream & os = cout ) const ;
  virtual void DisplayStats( ostream & os = cout ) const ;
  virtual void DisplayOverallStats( ostream & os = cout ) const ;
  virtual void DisplayOverallStatsCSV( ostream & os = cout ) const ;

  inline int getTime() { return _time;}
  Stats * getStats(const string & name) { return _stats[name]; }

};

template<class T>
ostream & operator<<(ostream & os, const vector<T> & v) {
  for(size_t i = 0; i < v.size() - 1; ++i) {
    os << v[i] << ",";
  }
  os << v[v.size()-1];
  return os;
}

#endif
<commit_msg>remove obsolete variable<commit_after>// $Id$

/*
Copyright (c) 2007-2011, Trustees of The Leland Stanford Junior University
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 Stanford University 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.
*/

#ifndef _TRAFFICMANAGER_HPP_
#define _TRAFFICMANAGER_HPP_

#include <list>
#include <map>
#include <set>
#include <cassert>

#include "module.hpp"
#include "config_utils.hpp"
#include "network.hpp"
#include "flit.hpp"
#include "buffer_state.hpp"
#include "stats.hpp"
#include "traffic.hpp"
#include "routefunc.hpp"
#include "outputset.hpp"
#include "injection.hpp"

//register the requests to a node
class PacketReplyInfo;

class TrafficManager : public Module {
protected:
  int _nodes;
  int _routers;

  vector<Network *> _net;
  vector<vector<Router *> > _router;

  // ============ Traffic ============

  int    _classes;

  vector<double> _load;

  vector<int>    _packet_size;

  /*false means all packet types are the same length "const_flits_per_packet"
   *All packets uses all VCS
   *packet types are generated randomly, essentially making it only 1 type
   *of packet in the network
   *
   *True means only request packets are generated and replies are generated
   *as a response to the requests, packets are now difference length, correspond
   *to "read_request_size" etc.
   */
  vector<int> _use_read_write;

  vector<int> _read_request_size;
  vector<int> _read_reply_size;
  vector<int> _write_request_size;
  vector<int> _write_reply_size;

  vector<string> _traffic;

  vector<int> _class_priority;

  map<int, pair<int, vector<int> > > _class_prio_map;

  vector<TrafficPattern *> _traffic_pattern;
  vector<InjectionProcess *> _injection_process;

  // ============ Message priorities ============

  enum ePriority { class_based, age_based, network_age_based, local_age_based, queue_length_based, hop_count_based, sequence_based, none };

  ePriority _pri_type;

  // ============ Injection VC states  ============

  vector<vector<BufferState *> > _buf_states;
  vector<vector<vector<int> > > _last_vc;

  // ============ Routing ============

  tRoutingFunction _rf;

  // ============ Injection queues ============

  vector<vector<int> > _qtime;
  vector<vector<bool> > _qdrained;
  vector<vector<list<Flit *> > > _partial_packets;

  vector<map<int, Flit *> > _total_in_flight_flits;
  vector<map<int, Flit *> > _measured_in_flight_flits;
  vector<map<int, Flit *> > _retired_packets;
  bool _empty_network;

  // ============ physical sub-networks ==========

  int _subnets;

  vector<int> _subnet;

  // ============ deadlock ==========

  int _deadlock_timer;
  int _deadlock_warn_timeout;

  // ============ request & replies ==========================

  vector<int> _sent_packets;
  vector<list<PacketReplyInfo*> > _repliesPending;
  vector<int> _requestsOutstanding;
  bool _replies_inherit_priority;

  // ============ Statistics ============

  vector<Stats *> _plat_stats;
  vector<double> _overall_min_plat;
  vector<double> _overall_avg_plat;
  vector<double> _overall_max_plat;

  vector<Stats *> _tlat_stats;
  vector<double> _overall_min_tlat;
  vector<double> _overall_avg_tlat;
  vector<double> _overall_max_tlat;

  vector<Stats *> _frag_stats;
  vector<double> _overall_min_frag;
  vector<double> _overall_avg_frag;
  vector<double> _overall_max_frag;

  vector<vector<Stats *> > _pair_plat;
  vector<vector<Stats *> > _pair_tlat;

  vector<Stats *> _hop_stats;
  vector<double> _overall_hop_stats;

  vector<vector<int> > _sent_flits;
  vector<double> _overall_min_sent;
  vector<double> _overall_avg_sent;
  vector<double> _overall_max_sent;
  vector<vector<int> > _accepted_flits;
  vector<double> _overall_min_accepted;
  vector<double> _overall_avg_accepted;
  vector<double> _overall_max_accepted;

  vector<int> _slowest_flit;

  map<string, Stats *> _stats;

  // ============ Simulation parameters ============

  enum eSimState { warming_up, running, draining, done };
  eSimState _sim_state;

  bool _measure_latency;

  int   _reset_time;
  int   _drain_time;

  int   _total_sims;
  int   _sample_period;
  int   _max_samples;
  int   _warmup_periods;

  int   _include_queuing;

  vector<int> _measure_stats;

  vector<double> _latency_thres;

  vector<double> _stopping_threshold;
  vector<double> _acc_stopping_threshold;

  vector<double> _warmup_threshold;
  vector<double> _acc_warmup_threshold;

  int _cur_id;
  int _cur_pid;
  int _cur_tid;
  int _time;

  set<int> _flits_to_watch;
  set<int> _packets_to_watch;
  set<int> _transactions_to_watch;

  bool _print_csv_results;
  bool _drain_measured_only;

  //flits to watch
  ostream * _stats_out;

#ifdef TRACK_FLOWS
  ostream * _active_packets_out;
  ostream * _injected_flits_out;
  ostream * _ejected_flits_out;
  ostream * _received_flits_out;
  ostream * _sent_flits_out;
  ostream * _stored_flits_out;
#endif

  // ============ Internal methods ============
protected:

  virtual void _RetireFlit( Flit *f, int dest );

  void _Inject();
  void _Step( );

  bool _PacketsOutstanding( ) const;

  virtual int  _IssuePacket( int source, int cl );
  void _GeneratePacket( int source, int size, int cl, int time );

  virtual void _ClearStats( );

  void _ComputeStats( const vector<int> & stats, int *sum, int *min = NULL, int *max = NULL, int *min_pos = NULL, int *max_pos = NULL ) const;

  virtual bool _SingleSim( );

  void _DisplayRemaining( ostream & os = cout ) const;

  void _LoadWatchList(const string & filename);

  virtual void _UpdateOverallStats();

  virtual string _OverallStatsCSV(int c = 0) const;

public:

  static TrafficManager * NewTrafficManager(Configuration const & config,
					    vector<Network *> const & net);

  TrafficManager( const Configuration &config, const vector<Network *> & net );
  virtual ~TrafficManager( );

  bool Run( );

  virtual void WriteStats( ostream & os = cout ) const ;
  virtual void DisplayStats( ostream & os = cout ) const ;
  virtual void DisplayOverallStats( ostream & os = cout ) const ;
  virtual void DisplayOverallStatsCSV( ostream & os = cout ) const ;

  inline int getTime() { return _time;}
  Stats * getStats(const string & name) { return _stats[name]; }

};

template<class T>
ostream & operator<<(ostream & os, const vector<T> & v) {
  for(size_t i = 0; i < v.size() - 1; ++i) {
    os << v[i] << ",";
  }
  os << v[v.size()-1];
  return os;
}

#endif
<|endoftext|>