⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simpleini.h

📁 This code is Address book code for Windows Mobile. This source code support windows mobile 5.0 over.
💻 H
📖 第 1 页 / 共 5 页
字号:
            return true;
        }
        ++a_pData;
    }

    // check for suffix
    if (IsSpace(*--a_pData)) {
        return true;
    }

    return false;
}

template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
bool
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::IsNewLineChar(
    SI_CHAR a_c
    ) const
{
    return (a_c == '\n' || a_c == '\r');
}

template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
bool
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::LoadMultiLineText(
    SI_CHAR *&          a_pData,
    const SI_CHAR *&    a_pVal,
    const SI_CHAR *     a_pTagName,
    bool                a_bAllowBlankLinesInComment
    ) const
{
    // we modify this data to strip all newlines down to a single '\n'
    // character. This means that on Windows we need to strip out some
    // characters which will make the data shorter.
    // i.e.  LINE1-LINE1\r\nLINE2-LINE2\0 will become
    //       LINE1-LINE1\nLINE2-LINE2\0
    // The pDataLine entry is the pointer to the location in memory that
    // the current line needs to start to run following the existing one.
    // This may be the same as pCurrLine in which case no move is needed.
    SI_CHAR * pDataLine = a_pData;
    SI_CHAR * pCurrLine;

    // value starts at the current line
    a_pVal = a_pData;

    // find the end tag. This tag must start in column 1 and be
    // followed by a newline. No whitespace removal is done while
    // searching for this tag.
    SI_CHAR cEndOfLineChar = *a_pData;
    for(;;) {
        // if we are loading comments then we need a comment character as
        // the first character on every line
        if (!a_pTagName && !IsComment(*a_pData)) {
            // if we aren't allowing blank lines then we're done
            if (!a_bAllowBlankLinesInComment) {
                break;
            }

            // if we are allowing blank lines then we only include them
            // in this comment if another comment follows, so read ahead
            // to find out.
            SI_CHAR * pCurr = a_pData;
            int nNewLines = 0;
            while (IsSpace(*pCurr)) {
                if (IsNewLineChar(*pCurr)) {
                    ++nNewLines;
                    SkipNewLine(pCurr);
                }
                else {
                    ++pCurr;
                }
            }

            // we have a comment, add the blank lines to the output
            // and continue processing from here
            if (IsComment(*pCurr)) {
                for (; nNewLines > 0; --nNewLines) *pDataLine++ = '\n';
                a_pData = pCurr;
                continue;
            }

            // the comment ends here
            break;
        }

        // find the end of this line
        pCurrLine = a_pData;
        while (*a_pData && !IsNewLineChar(*a_pData)) ++a_pData;

        // move this line down to the location that it should be if necessary
        if (pDataLine < pCurrLine) {
            size_t nLen = (size_t) (a_pData - pCurrLine);
            memmove(pDataLine, pCurrLine, nLen * sizeof(SI_CHAR));
            pDataLine[nLen] = '\0';
        }

        // end the line with a NULL
        cEndOfLineChar = *a_pData;
        *a_pData = 0;

        // if are looking for a tag then do the check now. This is done before
        // checking for end of the data, so that if we have the tag at the end
        // of the data then the tag is removed correctly.
        if (a_pTagName &&
            (!IsLess(pDataLine, a_pTagName) && !IsLess(a_pTagName, pDataLine)))
        {
            break;
        }

        // if we are at the end of the data then we just automatically end
        // this entry and return the current data.
        if (!cEndOfLineChar) {
            return true;
        }

        // otherwise we need to process this newline to ensure that it consists
        // of just a single \n character.
        pDataLine += (a_pData - pCurrLine);
        *a_pData = cEndOfLineChar;
        SkipNewLine(a_pData);
        *pDataLine++ = '\n';
    }

    // if we didn't find a comment at all then return false
    if (a_pVal == a_pData) {
        a_pVal = NULL;
        return false;
    }

    // the data (which ends at the end of the last line) needs to be
    // null-terminated BEFORE before the newline character(s). If the
    // user wants a new line in the multi-line data then they need to
    // add an empty line before the tag.
    *--pDataLine = '\0';

    // if looking for a tag and if we aren't at the end of the data,
    // then move a_pData to the start of the next line.
    if (a_pTagName && cEndOfLineChar) {
        SI_ASSERT(IsNewLineChar(cEndOfLineChar));
        *a_pData = cEndOfLineChar;
        SkipNewLine(a_pData);
    }

    return true;
}

template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
SI_Error
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::CopyString(
    const SI_CHAR *& a_pString
    )
{
    size_t uLen = 0;
    if (sizeof(SI_CHAR) == sizeof(char)) {
        uLen = strlen((const char *)a_pString);
    }
    else if (sizeof(SI_CHAR) == sizeof(wchar_t)) {
        uLen = wcslen((const wchar_t *)a_pString);
    }
    else {
        for ( ; a_pString[uLen]; ++uLen) /*loop*/ ;
    }
    ++uLen; // NULL character
    SI_CHAR * pCopy = new SI_CHAR[uLen];
    if (!pCopy) {
        return SI_NOMEM;
    }
    memcpy(pCopy, a_pString, sizeof(SI_CHAR)*uLen);
    m_strings.push_back(pCopy);
    a_pString = pCopy;
    return SI_OK;
}

template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
SI_Error
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::AddEntry(
    const SI_CHAR * a_pSection,
    const SI_CHAR * a_pKey,
    const SI_CHAR * a_pValue,
    const SI_CHAR * a_pComment,
    bool            a_bCopyStrings
    )
{
    SI_Error rc;
    bool bInserted = false;

    SI_ASSERT(!a_pComment || IsComment(*a_pComment));

    // if we are copying strings then make a copy of the comment now
    // because we will need it when we add the entry.
    if (a_bCopyStrings && a_pComment) {
        rc = CopyString(a_pComment);
        if (rc < 0) return rc;
    }

    // check for existence of the section first if we need string copies
    typename TSection::iterator iSection = m_data.end();
    if (a_bCopyStrings) {
        iSection = m_data.find(a_pSection);
        if (iSection == m_data.end()) {
            // if the section doesn't exist then we need a copy as the
            // string needs to last beyond the end of this function
            // because we will be inserting the section next
            rc = CopyString(a_pSection);
            if (rc < 0) return rc;
        }
    }

    // create the section entry
    if (iSection == m_data.end()) {
        Entry oKey(a_pSection, ++m_nOrder);
        if (a_pComment && (!a_pKey || !a_pValue)) {
            oKey.pComment = a_pComment;
        }
        typename TSection::value_type oEntry(oKey, TKeyVal());
        typedef typename TSection::iterator SectionIterator;
        std::pair<SectionIterator,bool> i =
            m_data.insert(oEntry);
        iSection = i.first;
        bInserted = true;
    }
    if (!a_pKey || !a_pValue) {
        // section only entries are specified with pItem and pVal as NULL
        return bInserted ? SI_INSERTED : SI_UPDATED;
    }

    // check for existence of the key
    TKeyVal & keyval = iSection->second;
    typename TKeyVal::iterator iKey = keyval.find(a_pKey);

    // make string copies if necessary
    if (a_bCopyStrings) {
        if (m_bAllowMultiKey || iKey == keyval.end()) {
            // if the key doesn't exist then we need a copy as the
            // string needs to last beyond the end of this function
            // because we will be inserting the key next
            rc = CopyString(a_pKey);
            if (rc < 0) return rc;
        }

        // we always need a copy of the value
        rc = CopyString(a_pValue);
        if (rc < 0) return rc;
    }

    // create the key entry
    if (iKey == keyval.end() || m_bAllowMultiKey) {
        Entry oKey(a_pKey, ++m_nOrder);
        if (a_pComment) {
            oKey.pComment = a_pComment;
        }
        typename TKeyVal::value_type oEntry(oKey, NULL);
        iKey = keyval.insert(oEntry);
        bInserted = true;
    }
    iKey->second = a_pValue;
    return bInserted ? SI_INSERTED : SI_UPDATED;
}

template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
const SI_CHAR *
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetValue(
    const SI_CHAR * a_pSection,
    const SI_CHAR * a_pKey,
    const SI_CHAR * a_pDefault,
    bool *          a_pHasMultiple
    ) const
{
    if (a_pHasMultiple) {
        *a_pHasMultiple = false;
    }
    if (!a_pSection || !a_pKey) {
        return a_pDefault;
    }
    typename TSection::const_iterator iSection = m_data.find(a_pSection);
    if (iSection == m_data.end()) {
        return a_pDefault;
    }
    typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey);
    if (iKeyVal == iSection->second.end()) {
        return a_pDefault;
    }

    // check for multiple entries with the same key
    if (m_bAllowMultiKey && a_pHasMultiple) {
        typename TKeyVal::const_iterator iTemp = iKeyVal;
        if (++iTemp != iSection->second.end()) {
            if (!IsLess(a_pKey, iTemp->first.pItem)) {
                *a_pHasMultiple = true;
            }
        }
    }

    return iKeyVal->second;
}

template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
bool
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetAllValues(
    const SI_CHAR * a_pSection,
    const SI_CHAR * a_pKey,
    TNamesDepend &  a_values
    ) const
{
    if (!a_pSection || !a_pKey) {
        return false;
    }
    typename TSection::const_iterator iSection = m_data.find(a_pSection);
    if (iSection == m_data.end()) {
        return false;
    }
    typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey);
    if (iKeyVal == iSection->second.end()) {
        return false;
    }

    // insert all values for this key
    a_values.push_back(iKeyVal->second);
    if (m_bAllowMultiKey) {
        ++iKeyVal;
        while (iKeyVal != iSection->second.end() && !IsLess(a_pKey, iKeyVal->first.pItem)) {
            a_values.push_back(Entry(iKeyVal->second, iKeyVal->first.nOrder));
            ++iKeyVal;
        }
    }

    return true;
}

template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
int
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetSectionSize(
    const SI_CHAR * a_pSection
    ) const
{
    if (!a_pSection) {
        return -1;
    }

    typename TSection::const_iterator iSection = m_data.find(a_pSection);
    if (iSection == m_data.end()) {
        return -1;
    }
    const TKeyVal & section = iSection->second;

    // if multi-key isn't permitted then the section size is
    // the number of keys that we have.
    if (!m_bAllowMultiKey || section.empty()) {
        return (int) section.size();
    }

    // otherwise we need to count them
    int nCount = 0;
    const SI_CHAR * pLastKey = NULL;
    typename TKeyVal::const_iterator iKeyVal = section.begin();
    for (int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n) {
        if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) {
            ++nCount;
            pLastKey = iKeyVal->first.pItem;
        }
    }
    return nCount;
}

template<class SI_CHAR, class

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -