1/* 2 * Copyright (c) 2011-2015, Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation and/or 13 * other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors 16 * may be used to endorse or promote products derived from this software without 17 * specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30#include "ArrayParameter.h" 31#include <sstream> // for istringstream 32#include "Tokenizer.h" 33#include "ParameterType.h" 34#include "ParameterAccessContext.h" 35#include "ConfigurationAccessContext.h" 36#include "ParameterBlackboard.h" 37#include "Utility.h" 38#include <assert.h> 39 40#define base CParameter 41 42using std::string; 43 44CArrayParameter::CArrayParameter(const string &strName, const CTypeElement *pTypeElement) 45 : base(strName, pTypeElement) 46{ 47} 48 49size_t CArrayParameter::getFootPrint() const 50{ 51 return getSize() * getArrayLength(); 52} 53 54// Array length 55size_t CArrayParameter::getArrayLength() const 56{ 57 return getTypeElement()->getArrayLength(); 58} 59 60// Element properties 61void CArrayParameter::showProperties(string &strResult) const 62{ 63 base::showProperties(strResult); 64 65 // Array length 66 strResult += "Array length: "; 67 strResult += std::to_string(getArrayLength()); 68 strResult += "\n"; 69} 70 71// User set/get 72bool CArrayParameter::accessValue(CPathNavigator &pathNavigator, string &strValue, bool bSet, 73 CParameterAccessContext ¶meterAccessContext) const 74{ 75 size_t index; 76 77 if (!getIndex(pathNavigator, index, parameterAccessContext)) { 78 79 return false; 80 } 81 82 if (bSet) { 83 // Set 84 if (index == (size_t)-1) { 85 86 // No index provided, start with 0 87 index = 0; 88 } 89 90 // Actually set values 91 if (!setValues(index, getOffset() - parameterAccessContext.getBaseOffset(), strValue, 92 parameterAccessContext)) { 93 return false; 94 } 95 96 // Synchronize 97 if (!sync(parameterAccessContext)) { 98 99 appendParameterPathToError(parameterAccessContext); 100 return false; 101 } 102 } else { 103 // Get 104 if (index == (size_t)-1) { 105 106 // Whole array requested 107 strValue = getValues(getOffset() - parameterAccessContext.getBaseOffset(), 108 parameterAccessContext); 109 110 } else { 111 // Scalar requested 112 CParameter::doGetValue(strValue, getOffset() + index * getSize(), 113 parameterAccessContext); 114 } 115 } 116 117 return true; 118} 119 120/// Actual parameter access 121// String access 122bool CArrayParameter::doSetValue(const string &value, size_t offset, 123 CParameterAccessContext ¶meterAccessContext) const 124{ 125 return setValues(0, offset, value, parameterAccessContext); 126} 127 128void CArrayParameter::doGetValue(string &value, size_t offset, 129 CParameterAccessContext ¶meterAccessContext) const 130{ 131 // Whole array requested 132 value = getValues(offset, parameterAccessContext); 133} 134 135// Boolean 136bool CArrayParameter::access(std::vector<bool> &abValues, bool bSet, 137 CParameterAccessContext ¶meterAccessContext) const 138{ 139 return accessValues(abValues, bSet, parameterAccessContext); 140} 141 142// Integer 143bool CArrayParameter::access(std::vector<uint32_t> &auiValues, bool bSet, 144 CParameterAccessContext ¶meterAccessContext) const 145{ 146 return accessValues(auiValues, bSet, parameterAccessContext); 147} 148 149// Signed Integer Access 150bool CArrayParameter::access(std::vector<int32_t> &aiValues, bool bSet, 151 CParameterAccessContext ¶meterAccessContext) const 152{ 153 return accessValues(aiValues, bSet, parameterAccessContext); 154} 155 156// Double Access 157bool CArrayParameter::access(std::vector<double> &adValues, bool bSet, 158 CParameterAccessContext ¶meterAccessContext) const 159{ 160 return accessValues(adValues, bSet, parameterAccessContext); 161} 162 163// String Access 164bool CArrayParameter::access(std::vector<string> &astrValues, bool bSet, 165 CParameterAccessContext ¶meterAccessContext) const 166{ 167 return accessValues(astrValues, bSet, parameterAccessContext); 168} 169 170// Dump 171string CArrayParameter::logValue(CParameterAccessContext &context) const 172{ 173 // Dump values 174 return getValues(0, context); 175} 176 177// Used for simulation and virtual subsystems 178void CArrayParameter::setDefaultValues(CParameterAccessContext ¶meterAccessContext) const 179{ 180 // Get default value from type 181 uint32_t uiDefaultValue = 182 static_cast<const CParameterType *>(getTypeElement())->getDefaultValue(); 183 184 // Write blackboard 185 CParameterBlackboard *pBlackboard = parameterAccessContext.getParameterBlackboard(); 186 187 // Process 188 size_t valueIndex; 189 size_t size = getSize(); 190 size_t offset = getOffset(); 191 size_t arrayLength = getArrayLength(); 192 193 for (valueIndex = 0; valueIndex < arrayLength; valueIndex++) { 194 195 // Beware this code works on little endian architectures only! 196 pBlackboard->writeInteger(&uiDefaultValue, size, offset); 197 198 offset += size; 199 } 200} 201 202// Index from path 203bool CArrayParameter::getIndex(CPathNavigator &pathNavigator, size_t &index, 204 CParameterAccessContext ¶meterAccessContext) const 205{ 206 index = (size_t)-1; 207 208 string *pStrChildName = pathNavigator.next(); 209 210 if (pStrChildName) { 211 212 // Check index is numeric 213 std::istringstream iss(*pStrChildName); 214 215 iss >> index; 216 217 if (!iss) { 218 219 parameterAccessContext.setError("Expected numerical expression as last item in " + 220 pathNavigator.getCurrentPath()); 221 222 return false; 223 } 224 225 if (index >= getArrayLength()) { 226 std::ostringstream oss; 227 228 oss << "Provided index out of range (max is " << getArrayLength() - 1 << ")"; 229 230 parameterAccessContext.setError(oss.str()); 231 232 return false; 233 } 234 235 // Check no other item provided in path 236 pStrChildName = pathNavigator.next(); 237 238 if (pStrChildName) { 239 240 // Should be leaf element 241 parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath()); 242 243 return false; 244 } 245 } 246 247 return true; 248} 249 250// Common set value processing 251bool CArrayParameter::setValues(size_t uiStartIndex, size_t offset, const string &strValue, 252 CParameterAccessContext ¶meterAccessContext) const 253{ 254 // Deal with value(s) 255 Tokenizer tok(strValue, Tokenizer::defaultDelimiters + ","); 256 257 std::vector<string> astrValues = tok.split(); 258 size_t nbValues = astrValues.size(); 259 260 // Check number of provided values 261 if (nbValues + uiStartIndex > getArrayLength()) { 262 263 // Out of bounds 264 parameterAccessContext.setError("Too many values provided"); 265 266 return false; 267 } 268 269 // Process 270 size_t valueIndex; 271 size_t size = getSize(); 272 offset += uiStartIndex * size; 273 274 for (valueIndex = 0; valueIndex < nbValues; valueIndex++) { 275 276 if (!doSet(astrValues[valueIndex], offset, parameterAccessContext)) { 277 278 // Append parameter path to error 279 parameterAccessContext.appendToError(" " + getPath() + "/" + 280 std::to_string(valueIndex + uiStartIndex)); 281 282 return false; 283 } 284 285 offset += size; 286 } 287 return true; 288} 289 290// Common get value processing 291string CArrayParameter::getValues(size_t offset, 292 CParameterAccessContext ¶meterAccessContext) const 293{ 294 size_t size = getSize(); 295 size_t arrayLength = getArrayLength(); 296 297 string output; 298 299 bool bFirst = true; 300 301 for (size_t valueIndex = 0; valueIndex < arrayLength; valueIndex++) { 302 string strReadValue; 303 304 doGet(strReadValue, offset, parameterAccessContext); 305 306 if (!bFirst) { 307 308 output += " "; 309 } else { 310 311 bFirst = false; 312 } 313 314 output += strReadValue; 315 316 offset += size; 317 } 318 319 return output; 320} 321 322// Generic Access 323template <typename type> 324bool CArrayParameter::accessValues(std::vector<type> &values, bool bSet, 325 CParameterAccessContext ¶meterAccessContext) const 326{ 327 if (bSet) { 328 329 // Set Value 330 if (!setValues(values, parameterAccessContext)) { 331 332 appendParameterPathToError(parameterAccessContext); 333 return false; 334 } 335 if (!sync(parameterAccessContext)) { 336 337 appendParameterPathToError(parameterAccessContext); 338 return false; 339 } 340 } else { 341 // Get Value 342 if (!getValues(values, parameterAccessContext)) { 343 344 appendParameterPathToError(parameterAccessContext); 345 return false; 346 } 347 } 348 return true; 349} 350 351template <typename type> 352bool CArrayParameter::setValues(const std::vector<type> &values, 353 CParameterAccessContext ¶meterAccessContext) const 354{ 355 size_t nbValues = getArrayLength(); 356 size_t size = getSize(); 357 size_t offset = getOffset(); 358 359 assert(values.size() == nbValues); 360 361 // Process 362 for (size_t valueIndex = 0; valueIndex < nbValues; valueIndex++) { 363 364 if (!doSet(values[valueIndex], offset, parameterAccessContext)) { 365 366 return false; 367 } 368 369 offset += size; 370 } 371 372 return true; 373} 374 375template <typename type> 376bool CArrayParameter::getValues(std::vector<type> &values, 377 CParameterAccessContext ¶meterAccessContext) const 378{ 379 size_t nbValues = getArrayLength(); 380 size_t size = getSize(); 381 size_t offset = getOffset(); 382 383 values.clear(); 384 385 for (size_t valueIndex = 0; valueIndex < nbValues; valueIndex++) { 386 type readValue; 387 388 if (!doGet(readValue, offset, parameterAccessContext)) { 389 390 return false; 391 } 392 393 values.push_back(readValue); 394 395 offset += size; 396 } 397 return true; 398} 399 400template <typename type> 401bool CArrayParameter::doSet(type value, size_t offset, 402 CParameterAccessContext ¶meterAccessContext) const 403{ 404 uint32_t uiData; 405 406 if (!static_cast<const CParameterType *>(getTypeElement()) 407 ->toBlackboard(value, uiData, parameterAccessContext)) { 408 409 return false; 410 } 411 // Write blackboard 412 CParameterBlackboard *pBlackboard = parameterAccessContext.getParameterBlackboard(); 413 414 // Beware this code works on little endian architectures only! 415 pBlackboard->writeInteger(&uiData, getSize(), offset); 416 417 return true; 418} 419 420template <typename type> 421bool CArrayParameter::doGet(type &value, size_t offset, 422 CParameterAccessContext ¶meterAccessContext) const 423{ 424 uint32_t uiData = 0; 425 426 // Read blackboard 427 const CParameterBlackboard *pBlackboard = parameterAccessContext.getParameterBlackboard(); 428 429 // Beware this code works on little endian architectures only! 430 pBlackboard->readInteger(&uiData, getSize(), offset); 431 432 return static_cast<const CParameterType *>(getTypeElement()) 433 ->fromBlackboard(value, uiData, parameterAccessContext); 434} 435