Changeset 69062 in vbox
- Timestamp:
- Oct 12, 2017 3:05:52 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 118342
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/inifile.h
r68317 r69062 77 77 78 78 /** 79 * Queries a value in a section.79 * Queries a named value in a section. 80 80 * 81 81 * The first matching value is returned. The matching is by default case … … 99 99 char *pszValue, size_t cbValue, size_t *pcbActual); 100 100 101 /** 102 * Queries a key-value pair in a section by ordinal. 103 * 104 * @returns IPRT status code. 105 * @retval VERR_NOT_FOUND if the section wasn't found or if it contains no pair 106 * with the given ordinal value. 107 * 108 * @param hIniFile The INI-file handle. 109 * @param pszSection The section name. Pass NULL to refer to the 110 * unsectioned key space at the top of the file. 111 * @param idxPair The pair to fetch (counting from 0). 112 * 113 * @param pszKey Where to return the key name. 114 * @param cbKey Size of the buffer @a pszKey points to. 115 * @param pcbKeyActual Where to return the actual key size excluding 116 * terminator on success. On VERR_BUFFER_OVERFLOW this 117 * will be set to the buffer size needed to hold the 118 * value, terminator included. Optional. 119 * 120 * @param pszValue Where to return the value. 121 * @param cbValue Size of the buffer @a pszValue points to. 122 * @param pcbValueActual Where to return the actual value size excluding 123 * terminator on success. On VERR_BUFFER_OVERFLOW this 124 * will be set to the buffer size needed to hold the 125 * value, terminator included. Optional. 126 */ 127 RTDECL(int) RTIniFileQueryPair(RTINIFILE hIniFile, const char *pszSection, uint32_t idxPair, 128 char *pszKey, size_t cbKey, size_t *pcbKeyActual, 129 char *pszValue, size_t cbValue, size_t *pcbValueActual); 130 101 131 102 132 /** @} */ -
trunk/include/iprt/mangling.h
r69011 r69062 1020 1020 # define RTIniFileRetain RT_MANGLER(RTIniFileRetain) 1021 1021 # define RTIniFileRelease RT_MANGLER(RTIniFileRelease) 1022 # define RTIniFileQueryPair RT_MANGLER(RTIniFileQueryPair) 1022 1023 # define RTIniFileQueryValue RT_MANGLER(RTIniFileQueryValue) 1023 1024 # define RTIsoFsClose RT_MANGLER(RTIsoFsClose) -
trunk/src/VBox/Runtime/common/misc/inifile.cpp
r69060 r69062 438 438 if (ch != '=') 439 439 { 440 /** @todo deal with escaped eq al signs? */440 /** @todo deal with escaped equal signs? */ 441 441 pszEqual = strchr(psz, '='); 442 442 if (pszEqual) … … 573 573 } 574 574 575 576 /** 577 * Worker for RTIniFileQueryPair. 578 * 579 * This can also be used to count the number of pairs in a section. 580 */ 581 static int rtIniFileQueryPairInSection(PRTINIFILEINT pThis, PRTINIFILESECTION pSection, uint32_t *pidxPair, 582 char *pszKey, size_t cbKey, size_t *pcbKeyActual, 583 char *pszValue, size_t cbValue, size_t *pcbValueActual) 584 { 585 uint32_t idxPair = *pidxPair; 586 587 /* 588 * Scan the section, looking for the matching key. 589 */ 590 Assert(pSection->cchSkipToValues <= pSection->cchSection); 591 const char * const pszEnd = &pThis->pszFile[pSection->offName + pSection->cchSection]; 592 const char * pszNext = pszEnd; 593 for (const char *psz = &pThis->pszFile[pSection->offName + pSection->cchSkipToValues]; 594 (uintptr_t)psz < (uintptr_t)pszEnd; 595 psz = pszNext) 596 { 597 /* Find start of next line so we can use 'continue' to skip a line. */ 598 pszNext = strchr(psz, '\n'); 599 if (pszNext) 600 pszNext++; 601 else 602 pszNext = pszEnd; 603 604 /* Skip leading spaces. */ 605 char ch; 606 while ((ch = *psz) != '\0' && RT_C_IS_SPACE(ch)) 607 psz++; 608 if ( ch != ';' /* comment line */ 609 && ch != '\n' /* empty line */ 610 && ch != '\r' /* empty line */ 611 && (uintptr_t)psz < (uintptr_t)pszEnd) 612 { 613 /* Find end of key name, if any. */ 614 const char *pszCurKey = psz; 615 size_t cchCurKey; 616 const char *pszEqual; 617 if (ch != '=') 618 { 619 /** @todo deal with escaped equal signs? */ 620 pszEqual = strchr(psz, '='); 621 if (pszEqual) 622 { 623 if ((uintptr_t)pszEqual < (uintptr_t)pszNext) 624 cchCurKey = pszEqual - pszCurKey; 625 else 626 continue; 627 } 628 else 629 break; 630 } 631 else 632 { 633 cchCurKey = 0; 634 pszEqual = psz; 635 } 636 637 /* Is this the pair we're looking for? */ 638 if (idxPair > 0) 639 idxPair--; 640 else 641 { 642 /* 643 * Yes it's the stuff we're looking for. 644 * Prepare the the return stuff. 645 */ 646 647 /* Strip trailing spaces from the key name. */ 648 while (cchCurKey > 0 && RT_C_IS_SPACE(pszCurKey[cchCurKey - 1])) 649 cchCurKey--; 650 651 /* Skip leading blanks from the value. */ 652 psz = pszEqual + 1; 653 while ((ch = *psz) && RT_C_IS_SPACE(ch) && ch != '\n') 654 psz++; 655 656 /* Strip trailing spaces from the value. */ 657 size_t cchCurValue = pszNext - psz; 658 while (cchCurValue > 1 && RT_C_IS_SPACE(psz[cchCurValue - 1])) 659 cchCurValue--; 660 661 /* Strip value quotes. */ 662 if ( cchCurValue > 2 663 && ( (ch = *psz) == '"' 664 || ch == '\'' ) 665 && psz[cchCurValue - 1] == ch) 666 { 667 cchCurValue -= 2; 668 psz++; 669 } 670 671 /* 672 * Copy the stuff out. 673 */ 674 if ( cchCurValue < cbValue 675 && cchCurKey < cbKey) 676 { 677 memcpy(pszKey, pszCurKey, cchCurKey); 678 pszKey[cchCurKey] = '\0'; 679 if (pcbKeyActual) 680 *pcbKeyActual = cchCurKey; 681 682 memcpy(pszValue, psz, cchCurValue); 683 pszValue[cchCurValue] = '\0'; 684 if (pcbValueActual) 685 *pcbValueActual = cchCurValue; 686 687 *pidxPair = 0; 688 return VINF_SUCCESS; 689 } 690 691 /* Buffer overflow. Copy out what we can. */ 692 if (cbKey > 0) 693 { 694 if (cchCurKey < cbKey) 695 cbKey = cchCurKey + 1; 696 memcpy(pszKey, pszCurKey, cbKey - 1); 697 pszKey[cbKey - 1] = '\0'; 698 } 699 if (pcbKeyActual) 700 *pcbKeyActual = cchCurKey + 1; 701 702 if (cbValue > 0) 703 { 704 if (cchCurValue < cbValue) 705 cbValue = cchCurValue + 1; 706 memcpy(pszValue, psz, cbValue - 1); 707 pszValue[cbValue - 1] = '\0'; 708 } 709 if (pcbValueActual) 710 *pcbValueActual = cchCurValue + 1; 711 712 *pidxPair = 0; 713 return VERR_BUFFER_OVERFLOW; 714 } 715 } 716 } 717 *pidxPair = idxPair; 718 return VERR_NOT_FOUND; 719 } 720 721 722 /** 723 * Queries a key-value pair in a section by ordinal. 724 * 725 * @returns IPRT status code. 726 * @retval VERR_NOT_FOUND if the section wasn't found or if it contains no pair 727 * with the given ordinal value. 728 * 729 * @param hIniFile The INI-file handle. 730 * @param pszSection The section name. Pass NULL to refer to the 731 * unsectioned key space at the top of the file. 732 * @param idxPair The pair to fetch (counting from 0). 733 * 734 * @param pszKey Where to return the key name. 735 * @param cbKey Size of the buffer @a pszKey points to. 736 * @param pcbKeyActual Where to return the actual key size excluding 737 * terminator on success. On VERR_BUFFER_OVERFLOW this 738 * will be set to the buffer size needed to hold the 739 * value, terminator included. Optional. 740 * 741 * @param pszValue Where to return the value. 742 * @param cbValue Size of the buffer @a pszValue points to. 743 * @param pcbValueActual Where to return the actual value size excluding 744 * terminator on success. On VERR_BUFFER_OVERFLOW this 745 * will be set to the buffer size needed to hold the 746 * value, terminator included. Optional. 747 */ 748 RTDECL(int) RTIniFileQueryPair(RTINIFILE hIniFile, const char *pszSection, uint32_t idxPair, 749 char *pszKey, size_t cbKey, size_t *pcbKeyActual, 750 char *pszValue, size_t cbValue, size_t *pcbValueActual) 751 { 752 /* 753 * Validate input. 754 */ 755 PRTINIFILEINT pThis = hIniFile; 756 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 757 AssertReturn(pThis->u32Magic == RTINIFILE_MAGIC, VERR_INVALID_HANDLE); 758 AssertPtrNullReturn(pszSection, VERR_INVALID_POINTER); 759 if (cbKey) 760 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); 761 AssertPtrNullReturn(pcbKeyActual, VERR_INVALID_POINTER); 762 if (cbValue) 763 AssertPtrReturn(pszValue, VERR_INVALID_POINTER); 764 AssertPtrNullReturn(pcbValueActual, VERR_INVALID_POINTER); 765 766 /* 767 * Search relevant sections. 768 */ 769 int rc; 770 if (pszSection == NULL) 771 rc = rtIniFileQueryPairInSection(pThis, &pThis->paSections[0], &idxPair, 772 pszKey, cbKey, pcbKeyActual, pszValue, cbValue, pcbValueActual); 773 else 774 { 775 rc = VERR_NOT_FOUND; 776 uint32_t const cchSection = (uint32_t)strlen(pszSection); 777 for (uint32_t iSection = 1; iSection < pThis->cSections; iSection++) 778 if ( pThis->paSections[iSection].cchName == cchSection 779 && RTStrNICmp(&pThis->pszFile[pThis->paSections[iSection].offName], pszSection, cchSection) == 0) 780 { 781 rc = rtIniFileQueryPairInSection(pThis, &pThis->paSections[iSection], &idxPair, 782 pszKey, cbKey, pcbKeyActual, pszValue, cbValue, pcbValueActual); 783 if (rc != VERR_NOT_FOUND) 784 break; 785 } 786 } 787 return rc; 788 } 789
Note:
See TracChangeset
for help on using the changeset viewer.