/*
|
* Copyright (c) 2011-2015, Intel Corporation
|
* All rights reserved.
|
*
|
* Redistribution and use in source and binary forms, with or without modification,
|
* are permitted provided that the following conditions are met:
|
*
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
* list of conditions and the following disclaimer.
|
*
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* this list of conditions and the following disclaimer in the documentation and/or
|
* other materials provided with the distribution.
|
*
|
* 3. Neither the name of the copyright holder 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 "EnumParameterType.h"
|
#include "EnumValuePair.h"
|
#include "ParameterAccessContext.h"
|
#include "convert.hpp"
|
|
#include <iomanip>
|
|
#define base CParameterType
|
|
using std::string;
|
|
CEnumParameterType::CEnumParameterType(const string &strName) : base(strName)
|
{
|
}
|
|
string CEnumParameterType::getKind() const
|
{
|
return "EnumParameter";
|
}
|
|
bool CEnumParameterType::childrenAreDynamic() const
|
{
|
return true;
|
}
|
|
// Element properties
|
void CEnumParameterType::showProperties(string &strResult) const
|
{
|
base::showProperties(strResult);
|
|
strResult += "Value Pairs:\n";
|
|
// Show all value pairs
|
size_t uiChild;
|
size_t uiNbChildren = getNbChildren();
|
|
for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
|
|
const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
|
|
strResult += "\tLiteral: \"";
|
strResult += pValuePair->getName();
|
strResult += "\", Numerical: ";
|
strResult += pValuePair->getNumericalAsString();
|
strResult += "\n";
|
}
|
}
|
|
bool CEnumParameterType::fromXml(const CXmlElement &xmlElement,
|
CXmlSerializingContext &serializingContext)
|
{
|
// Size in bits
|
size_t sizeInBits = 0;
|
if (not xmlElement.getAttribute("Size", sizeInBits)) {
|
return false;
|
}
|
|
// Size
|
setSize(sizeInBits / 8);
|
|
// Base
|
return base::fromXml(xmlElement, serializingContext);
|
}
|
|
// Conversion (tuning)
|
bool CEnumParameterType::toBlackboard(const string &strValue, uint32_t &uiValue,
|
CParameterAccessContext ¶meterAccessContext) const
|
{
|
int32_t iParsedUserValue = 0;
|
|
// Try to read the user-provided string as an integer
|
if (not convertTo(strValue, iParsedUserValue)) {
|
// If it fails to parse as an integer, first try to convert it from
|
// lexical to numerical space.
|
int32_t iNumerical;
|
if (not getNumerical(strValue, iNumerical)) {
|
|
parameterAccessContext.setError("Provided value '" + strValue +
|
"' is not part of the lexical space"
|
" or not within the numerical range.");
|
|
return false;
|
}
|
iParsedUserValue = iNumerical;
|
}
|
|
// Once it has been converted to a number (either through parsing or
|
// through lexical->numerical conversion), call the numerical overload of
|
// toBlackboard.
|
return toBlackboard(iParsedUserValue, uiValue, parameterAccessContext);
|
}
|
|
int32_t CEnumParameterType::getMin() const
|
{
|
// Enums are always signed, it means we have one less util bit
|
return -getMax() - 1;
|
}
|
|
int32_t CEnumParameterType::getMax() const
|
{
|
return getMaxValue<int32_t>();
|
}
|
|
bool CEnumParameterType::fromBlackboard(string &userValue, const uint32_t &value,
|
CParameterAccessContext &ctx) const
|
{
|
// Convert the raw value from the blackboard
|
int32_t signedValue = static_cast<int32_t>(value);
|
signExtend(signedValue);
|
|
// Take care of format
|
if (ctx.valueSpaceIsRaw()) {
|
|
// Format
|
std::ostringstream sstream;
|
|
// Numerical format requested
|
if (ctx.outputRawFormatIsHex()) {
|
|
// Hexa display with unecessary bits cleared out
|
sstream << "0x" << std::hex << std::uppercase
|
<< std::setw(static_cast<int>(getSize() * 2)) << std::setfill('0')
|
<< makeEncodable(value);
|
|
userValue = sstream.str();
|
} else {
|
userValue = std::to_string(value);
|
}
|
} else {
|
// Literal display requested (should succeed)
|
getLiteral(signedValue, userValue);
|
}
|
return true;
|
}
|
|
// Value access
|
bool CEnumParameterType::toBlackboard(int32_t userValue, uint32_t &value,
|
CParameterAccessContext ¶meterAccessContext) const
|
{
|
// Take care of format
|
if (parameterAccessContext.valueSpaceIsRaw()) {
|
signExtend(userValue);
|
}
|
|
if (!checkValueAgainstSpace(userValue)) {
|
|
parameterAccessContext.setError(std::to_string(userValue) +
|
" is not part of numerical space.");
|
|
return false;
|
}
|
|
if (userValue < getMin() or userValue > getMax()) {
|
|
// FIXME: values provided as hexa (either on command line or in a config
|
// file will appear in decimal base instead of hexa base...
|
parameterAccessContext.setError(
|
"Value " + std::to_string(userValue) + " standing out of admitted range [" +
|
std::to_string(getMin()) + ", " + std::to_string(getMax()) + "] for " + getKind());
|
return false;
|
}
|
|
value = static_cast<uint32_t>(userValue);
|
|
return true;
|
}
|
|
bool CEnumParameterType::fromBlackboard(int32_t &userValue, uint32_t value,
|
CParameterAccessContext & /*ctx*/) const
|
{
|
int32_t signedValue = static_cast<int32_t>(value);
|
|
// Sign extend
|
signExtend(signedValue);
|
|
userValue = signedValue;
|
|
return true;
|
}
|
|
// Default value handling (simulation only)
|
uint32_t CEnumParameterType::getDefaultValue() const
|
{
|
if (!getNbChildren()) {
|
|
return 0;
|
}
|
|
// Return first available numerical
|
return static_cast<const CEnumValuePair *>(getChild(0))->getNumerical();
|
}
|
|
// Literal - numerical conversions
|
bool CEnumParameterType::getLiteral(int32_t iNumerical, string &strLiteral) const
|
{
|
size_t uiChild;
|
size_t uiNbChildren = getNbChildren();
|
|
for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
|
|
const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
|
|
if (pValuePair->getNumerical() == iNumerical) {
|
|
strLiteral = pValuePair->getName();
|
|
return true;
|
}
|
}
|
|
return false;
|
}
|
|
bool CEnumParameterType::getNumerical(const string &strLiteral, int32_t &iNumerical) const
|
{
|
size_t uiChild;
|
size_t uiNbChildren = getNbChildren();
|
|
for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
|
|
const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
|
|
if (pValuePair->getName() == strLiteral) {
|
|
iNumerical = pValuePair->getNumerical();
|
|
return true;
|
}
|
}
|
|
return false;
|
}
|
|
// Numerical validity of the enum value
|
bool CEnumParameterType::checkValueAgainstSpace(int32_t iNumerical) const
|
{
|
// Check that the value is part of the allowed values for this kind of enum
|
size_t uiChild;
|
size_t uiNbChildren = getNbChildren();
|
|
for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
|
|
const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
|
|
if (pValuePair->getNumerical() == iNumerical) {
|
|
return true;
|
}
|
}
|
|
return false;
|
}
|
|
// From IXmlSource
|
void CEnumParameterType::toXml(CXmlElement &xmlElement,
|
CXmlSerializingContext &serializingContext) const
|
{
|
// Size
|
xmlElement.setAttribute("Size", getSize() * 8);
|
|
base::toXml(xmlElement, serializingContext);
|
}
|