1 /****************************************************************************** 2 * 3 * Copyright (C) 1999-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /****************************************************************************** 20 * 21 * The original Work has been changed by NXP Semiconductors. 22 * 23 * Copyright (C) 2013-2014 NXP Semiconductors 24 * 25 * Licensed under the Apache License, Version 2.0 (the "License"); 26 * you may not use this file except in compliance with the License. 27 * You may obtain a copy of the License at 28 * 29 * http://www.apache.org/licenses/LICENSE-2.0 30 * 31 * Unless required by applicable law or agreed to in writing, software 32 * distributed under the License is distributed on an "AS IS" BASIS, 33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 34 * See the License for the specific language governing permissions and 35 * limitations under the License. 36 * 37 ******************************************************************************/ 38 /****************************************************************************** 39 * 40 * The original Work has been changed by Samsung Electronics. 41 42 * 43 * Copyright (C) 2018 Samsung Electronics, System LSI Division 44 * 45 * Licensed under the Apache License, Version 2.0 (the "License"); 46 * you may not use this file except in compliance with the License. 47 * You may obtain a copy of the License at 48 * 49 * http://www.apache.org/licenses/LICENSE-2.0 50 * 51 * Unless required by applicable law or agreed to in writing, software 52 * distributed under the License is distributed on an "AS IS" BASIS, 53 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 54 * See the License for the specific language governing permissions and 55 * limitations under the License. 56 * 57 ******************************************************************************/ 58 #include <log/log.h> 59 #include <stdio.h> 60 #include <sys/stat.h> 61 #include <list> 62 #include <string> 63 #include <vector> 64 65 #include <config.h> 66 #include <cutils/properties.h> 67 68 #include <hal.h> 69 70 #if GENERIC_TARGET 71 const char alternative_config_path[] = "/data/vendor/nfc/"; 72 #else 73 const char alternative_config_path[] = ""; 74 #endif 75 76 #if 1 77 const char* transport_config_paths[] = {"/odm/etc/", "/vendor/etc/", "/etc/"}; 78 #else 79 const char* transport_config_paths[] = {"res/"}; 80 #endif 81 const int transport_config_path_size = 82 (sizeof(transport_config_paths) / sizeof(transport_config_paths[0])); 83 84 #define config_name "libnfc-sec-vendor.conf" 85 #define extra_config_base "libnfc-sec-vendor" 86 #define extra_config_ext ".conf" 87 #define IsStringValue 0x80000000 88 89 #if (NFC_SEC_NOT_OPEN_INCLUDED == TRUE) 90 91 std::string UserPrefix; 92 93 extern "C" void Set_user_prefix(char* field) { 94 UserPrefix.erase(); 95 96 if (field != NULL) UserPrefix = field; 97 } 98 #endif 99 100 namespace { 101 102 size_t readConfigFile(const char* fileName, uint8_t** p_data) { 103 FILE* fd = fopen(fileName, "rb"); 104 if (fd == nullptr) return 0; 105 106 fseek(fd, 0L, SEEK_END); 107 const size_t file_size = ftell(fd); 108 rewind(fd); 109 110 uint8_t* buffer = new uint8_t[file_size]; 111 size_t read = fread(buffer, file_size, 1, fd); 112 fclose(fd); 113 114 if (read == 1) { 115 *p_data = buffer; 116 return file_size; 117 } 118 119 delete[] buffer; 120 return 0; 121 } 122 123 } // namespace 124 125 using namespace ::std; 126 127 class CNfcParam : public string { 128 public: 129 CNfcParam(); 130 CNfcParam(const char* name, const string& value); 131 CNfcParam(const char* name, unsigned long value); 132 virtual ~CNfcParam(); 133 unsigned long numValue() const { return m_numValue; } 134 const char* str_value() const { return m_str_value.c_str(); } 135 size_t str_len() const { return m_str_value.length(); } 136 137 private: 138 string m_str_value; 139 unsigned long m_numValue; 140 }; 141 142 class CNfcConfig : public vector<const CNfcParam*> { 143 public: 144 virtual ~CNfcConfig(); 145 static CNfcConfig& GetInstance(); 146 friend void readOptionalConfig(const char* optional); 147 148 bool getValue(const char* name, char* pValue, size_t len) const; 149 bool getValue(const char* name, unsigned long& rValue) const; 150 bool getValue(const char* name, unsigned short& rValue) const; 151 bool getValue(const char* name, char* pValue, long len, long* readlen) const; 152 #if (NFC_SEC_NOT_OPEN_INCLUDED == TRUE) 153 const CNfcParam* _find(const char* p_name) const; 154 #endif 155 const CNfcParam* find(const char* p_name) const; 156 void clean(); 157 158 private: 159 CNfcConfig(); 160 bool readConfig(const char* name, bool bResetContent); 161 void moveFromList(); 162 void moveToList(); 163 void add(const CNfcParam* pParam); 164 list<const CNfcParam*> m_list; 165 bool mValidFile; 166 unsigned long state; 167 168 inline bool Is(unsigned long f) { return (state & f) == f; } 169 inline void Set(unsigned long f) { state |= f; } 170 inline void Reset(unsigned long f) { state &= ~f; } 171 }; 172 173 /******************************************************************************* 174 ** 175 ** Function: isPrintable() 176 ** 177 ** Description: determine if 'c' is printable 178 ** 179 ** Returns: 1, if printable, otherwise 0 180 ** 181 *******************************************************************************/ 182 inline bool isPrintable(char c) { 183 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || 184 (c >= '0' && c <= '9') || 185 #if (NFC_SEC_NOT_OPEN_INCLUDED == TRUE) 186 (c == '+') || 187 #endif 188 c == '/' || c == '_' || c == '-' || c == '.'; 189 } 190 191 /******************************************************************************* 192 ** 193 ** Function: isDigit() 194 ** 195 ** Description: determine if 'c' is numeral digit 196 ** 197 ** Returns: true, if numerical digit 198 ** 199 *******************************************************************************/ 200 inline bool isDigit(char c, int base) { 201 if ('0' <= c && c <= '9') return true; 202 if (base == 16) { 203 if (('A' <= c && c <= 'F') || ('a' <= c && c <= 'f')) return true; 204 } 205 return false; 206 } 207 208 /******************************************************************************* 209 ** 210 ** Function: getDigitValue() 211 ** 212 ** Description: return numerical value of a decimal or hex char 213 ** 214 ** Returns: numerical value if decimal or hex char, otherwise 0 215 ** 216 *******************************************************************************/ 217 inline int getDigitValue(char c, int base) { 218 if ('0' <= c && c <= '9') return c - '0'; 219 if (base == 16) { 220 if ('A' <= c && c <= 'F') 221 return c - 'A' + 10; 222 else if ('a' <= c && c <= 'f') 223 return c - 'a' + 10; 224 } 225 return 0; 226 } 227 228 /******************************************************************************* 229 ** 230 ** Function: findConfigFilePathFromTransportConfigPaths() 231 ** 232 ** Description: find a config file path with a given config name from transport 233 ** config paths 234 ** 235 ** Returns: none 236 ** 237 *******************************************************************************/ 238 void findConfigFilePathFromTransportConfigPaths(const string& configName, 239 string& filePath) { 240 for (int i = 0; i < transport_config_path_size - 1; i++) { 241 filePath.assign(transport_config_paths[i]); 242 filePath += configName; 243 struct stat file_stat; 244 if (stat(filePath.c_str(), &file_stat) == 0 && S_ISREG(file_stat.st_mode)) { 245 return; 246 } 247 } 248 filePath.assign(transport_config_paths[transport_config_path_size - 1]); 249 filePath += configName; 250 } 251 252 /******************************************************************************* 253 ** 254 ** Function: CNfcConfig::readConfig() 255 ** 256 ** Description: read Config settings and parse them into a linked list 257 ** move the element from linked list to a array at the end 258 ** 259 ** Returns: 1, if there are any config data, 0 otherwise 260 ** 261 *******************************************************************************/ 262 bool CNfcConfig::readConfig(const char* name, bool bResetContent) { 263 enum { 264 BEGIN_LINE = 1, 265 TOKEN, 266 STR_VALUE, 267 NUM_VALUE, 268 BEGIN_HEX, 269 BEGIN_QUOTE, 270 END_LINE 271 }; 272 273 uint8_t* p_config = nullptr; 274 size_t config_size = readConfigFile(name, &p_config); 275 if (p_config == nullptr) { 276 ALOGE("%s Cannot open config file %s\n", __func__, name); 277 if (bResetContent) { 278 ALOGE("%s Using default value for all settings\n", __func__); 279 mValidFile = false; 280 } 281 return false; 282 } 283 284 string token; 285 string strValue; 286 unsigned long numValue = 0; 287 CNfcParam* pParam = NULL; 288 int i = 0; 289 int base = 0; 290 char c; 291 int bflag = 0; 292 state = BEGIN_LINE; 293 294 mValidFile = true; 295 if (size() > 0) { 296 if (bResetContent) 297 clean(); 298 else 299 moveToList(); 300 } 301 302 for (size_t offset = 0; offset != config_size; ++offset) { 303 c = p_config[offset]; 304 switch (state & 0xff) { 305 case BEGIN_LINE: 306 if (c == '#') 307 state = END_LINE; 308 else if (isPrintable(c)) { 309 i = 0; 310 token.erase(); 311 strValue.erase(); 312 state = TOKEN; 313 token.push_back(c); 314 } 315 break; 316 case TOKEN: 317 if (c == '=') { 318 token.push_back('\0'); 319 state = BEGIN_QUOTE; 320 } else if (isPrintable(c)) 321 token.push_back(c); 322 else 323 state = END_LINE; 324 break; 325 case BEGIN_QUOTE: 326 if (c == '"') { 327 state = STR_VALUE; 328 base = 0; 329 } else if (c == '0') 330 state = BEGIN_HEX; 331 else if (isDigit(c, 10)) { 332 state = NUM_VALUE; 333 base = 10; 334 numValue = getDigitValue(c, base); 335 i = 0; 336 } else if (c == '{') { 337 state = NUM_VALUE; 338 bflag = 1; 339 base = 16; 340 i = 0; 341 Set(IsStringValue); 342 } else 343 state = END_LINE; 344 break; 345 case BEGIN_HEX: 346 if (c == 'x' || c == 'X') { 347 state = NUM_VALUE; 348 base = 16; 349 numValue = 0; 350 i = 0; 351 break; 352 } else if (isDigit(c, 10)) { 353 state = NUM_VALUE; 354 base = 10; 355 numValue = getDigitValue(c, base); 356 break; 357 } else if (c != '\n' && c != '\r') { 358 state = END_LINE; 359 break; 360 } 361 // fall through to numValue to handle numValue 362 [[fallthrough]]; 363 364 case NUM_VALUE: 365 if (isDigit(c, base)) { 366 numValue *= base; 367 numValue += getDigitValue(c, base); 368 ++i; 369 } else if (bflag == 1 && 370 (c == ' ' || c == '\r' || c == '\n' || c == '\t')) { 371 break; 372 } else if (base == 16 && 373 (c == ',' || c == ':' || c == '-' || c == ' ' || c == '}')) { 374 if (c == '}') { 375 bflag = 0; 376 } 377 if (i > 0) { 378 int n = (i + 1) / 2; 379 while (n-- > 0) { 380 numValue = numValue >> (n * 8); 381 unsigned char c = (numValue)&0xFF; 382 strValue.push_back(c); 383 } 384 } 385 386 Set(IsStringValue); 387 numValue = 0; 388 i = 0; 389 } else { 390 if (c == '\n' || c == '\r') { 391 if (bflag == 0) { 392 state = BEGIN_LINE; 393 } 394 } else { 395 if (bflag == 0) { 396 state = END_LINE; 397 } 398 } 399 if (Is(IsStringValue) && base == 16 && i > 0) { 400 int n = (i + 1) / 2; 401 while (n-- > 0) strValue.push_back(((numValue >> (n * 8)) & 0xFF)); 402 } 403 if (strValue.length() > 0) 404 pParam = new CNfcParam(token.c_str(), strValue); 405 else 406 pParam = new CNfcParam(token.c_str(), numValue); 407 add(pParam); 408 strValue.erase(); 409 numValue = 0; 410 } 411 break; 412 case STR_VALUE: 413 if (c == '"') { 414 strValue.push_back('\0'); 415 state = END_LINE; 416 pParam = new CNfcParam(token.c_str(), strValue); 417 add(pParam); 418 } else if (isPrintable(c)) 419 strValue.push_back(c); 420 break; 421 case END_LINE: 422 if (c == '\n' || c == '\r') state = BEGIN_LINE; 423 break; 424 default: 425 break; 426 } 427 } 428 429 delete[] p_config; 430 431 moveFromList(); 432 return size() > 0; 433 } 434 435 /******************************************************************************* 436 ** 437 ** Function: CNfcConfig::CNfcConfig() 438 ** 439 ** Description: class constructor 440 ** 441 ** Returns: none 442 ** 443 *******************************************************************************/ 444 CNfcConfig::CNfcConfig() : mValidFile(true), state(0) {} 445 446 /******************************************************************************* 447 ** 448 ** Function: CNfcConfig::~CNfcConfig() 449 ** 450 ** Description: class destructor 451 ** 452 ** Returns: none 453 ** 454 *******************************************************************************/ 455 CNfcConfig::~CNfcConfig() {} 456 457 /******************************************************************************* 458 ** 459 ** Function: CNfcConfig::GetInstance() 460 ** 461 ** Description: get class singleton object 462 ** 463 ** Returns: none 464 ** 465 *******************************************************************************/ 466 CNfcConfig& CNfcConfig::GetInstance() { 467 static CNfcConfig theInstance; 468 if (theInstance.size() == 0 && theInstance.mValidFile) { 469 string strPath; 470 if (alternative_config_path[0] != '\0') { 471 strPath.assign(alternative_config_path); 472 strPath += config_name; 473 theInstance.readConfig(strPath.c_str(), true); 474 if (!theInstance.empty()) { 475 return theInstance; 476 } 477 } 478 findConfigFilePathFromTransportConfigPaths(config_name, strPath); 479 theInstance.readConfig(strPath.c_str(), true); 480 } 481 482 return theInstance; 483 } 484 485 /******************************************************************************* 486 ** 487 ** Function: CNfcConfig::getValue() 488 ** 489 ** Description: get a string value of a setting 490 ** 491 ** Returns: true if setting exists 492 ** false if setting does not exist 493 ** 494 *******************************************************************************/ 495 bool CNfcConfig::getValue(const char* name, char* pValue, size_t len) const { 496 const CNfcParam* pParam = find(name); 497 if (pParam == NULL) return false; 498 499 if (pParam->str_len() > 0) { 500 memset(pValue, 0, len); 501 memcpy(pValue, pParam->str_value(), pParam->str_len()); 502 return true; 503 } 504 return false; 505 } 506 507 bool CNfcConfig::getValue(const char* name, char* pValue, long len, 508 long* readlen) const { 509 const CNfcParam* pParam = find(name); 510 if (pParam == NULL) return false; 511 512 if (pParam->str_len() > 0) { 513 if (pParam->str_len() <= (unsigned long)len) { 514 memset(pValue, 0, len); 515 memcpy(pValue, pParam->str_value(), pParam->str_len()); 516 *readlen = pParam->str_len(); 517 } else { 518 *readlen = -1; 519 } 520 521 return true; 522 } 523 return false; 524 } 525 526 /******************************************************************************* 527 ** 528 ** Function: CNfcConfig::getValue() 529 ** 530 ** Description: get a long numerical value of a setting 531 ** 532 ** Returns: true if setting exists 533 ** false if setting does not exist 534 ** 535 *******************************************************************************/ 536 bool CNfcConfig::getValue(const char* name, unsigned long& rValue) const { 537 const CNfcParam* pParam = find(name); 538 if (pParam == NULL) return false; 539 540 if (pParam->str_len() == 0) { 541 rValue = static_cast<unsigned long>(pParam->numValue()); 542 return true; 543 } 544 return false; 545 } 546 547 /******************************************************************************* 548 ** 549 ** Function: CNfcConfig::getValue() 550 ** 551 ** Description: get a short numerical value of a setting 552 ** 553 ** Returns: true if setting exists 554 ** false if setting does not exist 555 ** 556 *******************************************************************************/ 557 bool CNfcConfig::getValue(const char* name, unsigned short& rValue) const { 558 const CNfcParam* pParam = find(name); 559 if (pParam == NULL) return false; 560 561 if (pParam->str_len() == 0) { 562 rValue = static_cast<unsigned short>(pParam->numValue()); 563 return true; 564 } 565 return false; 566 } 567 568 /******************************************************************************* 569 ** 570 ** Function: CNfcConfig::find() 571 ** 572 ** Description: search if a setting exist in the setting array 573 ** 574 ** Returns: pointer to the setting object 575 ** 576 *******************************************************************************/ 577 #if (NFC_SEC_NOT_OPEN_INCLUDED == TRUE) 578 const CNfcParam* CNfcConfig::find(const char* p_name) const { 579 if (size() == 0) return NULL; 580 581 std::string firstField; 582 583 if (UserPrefix.size() > 0) { 584 // Find first priority field 585 firstField.erase(); 586 firstField += "+"; 587 firstField += UserPrefix; 588 firstField += "_"; 589 firstField += p_name; 590 591 const CNfcParam* ret = _find(firstField.c_str()); 592 if (ret != NULL) return ret; 593 } 594 595 return _find(p_name); 596 } 597 598 const CNfcParam* CNfcConfig::_find(const char* p_name) const { 599 for (const_iterator it = begin(), itEnd = end(); it != itEnd; ++it) { 600 if (**it < p_name) 601 continue; 602 else if (**it == p_name) { 603 if ((*it)->str_len() > 0) 604 ALOGD("%s found %s=%s\n", __func__, p_name, (*it)->str_value()); 605 else 606 ALOGD("%s found %s=(0x%lX)\n", __func__, p_name, (*it)->numValue()); 607 return *it; 608 } else 609 break; 610 } 611 612 return NULL; 613 } 614 #else 615 const CNfcParam* CNfcConfig::find(const char* p_name) const { 616 if (size() == 0) return NULL; 617 618 for (const_iterator it = begin(), itEnd = end(); it != itEnd; ++it) { 619 if (**it < p_name) { 620 continue; 621 } else if (**it == p_name) { 622 if ((*it)->str_len() > 0) { 623 ALOGD("%s found %s=%s\n", __func__, p_name, (*it)->str_value()); 624 625 } else { 626 ALOGD("%s found %s=(0x%lx)\n", __func__, p_name, (*it)->numValue()); 627 } 628 return *it; 629 } else 630 break; 631 } 632 return NULL; 633 } 634 #endif 635 /******************************************************************************* 636 ** 637 ** Function: CNfcConfig::clean() 638 ** 639 ** Description: reset the setting array 640 ** 641 ** Returns: none 642 ** 643 *******************************************************************************/ 644 void CNfcConfig::clean() { 645 if (size() == 0) return; 646 647 for (iterator it = begin(), itEnd = end(); it != itEnd; ++it) delete *it; 648 clear(); 649 } 650 651 /******************************************************************************* 652 ** 653 ** Function: CNfcConfig::Add() 654 ** 655 ** Description: add a setting object to the list 656 ** 657 ** Returns: none 658 ** 659 *******************************************************************************/ 660 void CNfcConfig::add(const CNfcParam* pParam) { 661 if (m_list.size() == 0) { 662 m_list.push_back(pParam); 663 return; 664 } 665 for (list<const CNfcParam*>::iterator it = m_list.begin(), 666 itEnd = m_list.end(); 667 it != itEnd; ++it) { 668 if (**it < pParam->c_str()) continue; 669 m_list.insert(it, pParam); 670 return; 671 } 672 m_list.push_back(pParam); 673 } 674 675 /******************************************************************************* 676 ** 677 ** Function: CNfcConfig::moveFromList() 678 ** 679 ** Description: move the setting object from list to array 680 ** 681 ** Returns: none 682 ** 683 *******************************************************************************/ 684 void CNfcConfig::moveFromList() { 685 if (m_list.size() == 0) return; 686 687 for (list<const CNfcParam*>::iterator it = m_list.begin(), 688 itEnd = m_list.end(); 689 it != itEnd; ++it) 690 push_back(*it); 691 m_list.clear(); 692 } 693 694 /******************************************************************************* 695 ** 696 ** Function: CNfcConfig::moveToList() 697 ** 698 ** Description: move the setting object from array to list 699 ** 700 ** Returns: none 701 ** 702 *******************************************************************************/ 703 void CNfcConfig::moveToList() { 704 if (m_list.size() != 0) m_list.clear(); 705 706 for (iterator it = begin(), itEnd = end(); it != itEnd; ++it) 707 m_list.push_back(*it); 708 clear(); 709 } 710 /******************************************************************************* 711 ** 712 ** Function: CNfcParam::CNfcParam() 713 ** 714 ** Description: class constructor 715 ** 716 ** Returns: none 717 ** 718 *******************************************************************************/ 719 CNfcParam::CNfcParam() : m_numValue(0) {} 720 721 /******************************************************************************* 722 ** 723 ** Function: CNfcParam::~CNfcParam() 724 ** 725 ** Description: class destructor 726 ** 727 ** Returns: none 728 ** 729 *******************************************************************************/ 730 CNfcParam::~CNfcParam() {} 731 732 /******************************************************************************* 733 ** 734 ** Function: CNfcParam::CNfcParam() 735 ** 736 ** Description: class copy constructor 737 ** 738 ** Returns: none 739 ** 740 *******************************************************************************/ 741 CNfcParam::CNfcParam(const char* name, const string& value) 742 : string(name), m_str_value(value), m_numValue(0) {} 743 744 /******************************************************************************* 745 ** 746 ** Function: CNfcParam::CNfcParam() 747 ** 748 ** Description: class copy constructor 749 ** 750 ** Returns: none 751 ** 752 *******************************************************************************/ 753 CNfcParam::CNfcParam(const char* name, unsigned long value) 754 : string(name), m_numValue(value) {} 755 756 /******************************************************************************* 757 ** 758 ** Function: GetStrValue 759 ** 760 ** Description: API function for getting a string value of a setting 761 ** 762 ** Returns: True if found, otherwise False. 763 ** 764 */ 765 extern "C" int GetStrValue(const char* name, char* pValue, // SLSI 766 unsigned long len) { 767 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 768 769 return rConfig.getValue(name, pValue, len); 770 } 771 /******************************************************************************* 772 ** 773 ** Function: GetByteArrayValue() 774 ** 775 ** Description: Read byte array value from the config file. 776 ** 777 ** Parameters: 778 ** name - name of the config param to read. 779 ** pValue - pointer to input buffer. 780 ** bufflen - input buffer length. 781 ** len - out parameter to return the number of bytes read from 782 ** config file, return -1 in case bufflen is not enough. 783 ** 784 ** Returns: TRUE[1] if config param name is found in the config file, else 785 ** FALSE[0] 786 ** 787 *******************************************************************************/ 788 extern "C" int GetByteArrayValue(const char* name, char* pValue, // SLSI 789 long bufflen, long* len) { 790 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 791 792 return rConfig.getValue(name, pValue, bufflen, len); 793 } 794 /******************************************************************************* 795 ** 796 ** Function: GetNumValue 797 ** 798 ** Description: API function for getting a numerical value of a setting 799 ** 800 ** Returns: true, if successful 801 ** 802 *******************************************************************************/ 803 extern "C" int GetNumValue(const char* name, void* pValue, // SLSI 804 unsigned long len) { 805 if (!pValue) return false; 806 807 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 808 const CNfcParam* pParam = rConfig.find(name); 809 810 if (pParam == NULL) return false; 811 unsigned long v = pParam->numValue(); 812 if (v == 0 && pParam->str_len() > 0 && pParam->str_len() < 4) { 813 const unsigned char* p = (const unsigned char*)pParam->str_value(); 814 for (unsigned int i = 0; i < pParam->str_len(); ++i) { 815 v *= 256; 816 v += *p++; 817 } 818 } 819 switch (len) { 820 case sizeof(unsigned long): 821 *(static_cast<unsigned long*>(pValue)) = (unsigned long)v; 822 break; 823 case sizeof(unsigned short): 824 *(static_cast<unsigned short*>(pValue)) = (unsigned short)v; 825 break; 826 case sizeof(unsigned char): 827 *(static_cast<unsigned char*>(pValue)) = (unsigned char)v; 828 break; 829 default: 830 return false; 831 } 832 return true; 833 } 834