public string Resolve()

in Sharpmake/Resolver.cs [315:461]


        public string Resolve(string str, object fallbackValue, out bool wasChanged)
        {
            wasChanged = false;

            // Early out
            if (str == null)
                return str;

            StringBuilder builder = null;

            // Support escape char for MemberPath
            // [[MyString]] will convert to [MyString]
            bool containsEscaped = false;

            while (true)
            {
                int startMatch = 0;
                int nbrReplacements = 0;
                int currentSearchIndex = 0;
                int endMatch = 0;
                int strLength = str.Length;
                while (currentSearchIndex < strLength)
                {
                    // Find match range.
                    startMatch = -1;
                    int matchTypeIndex;
                    for (matchTypeIndex = 0; matchTypeIndex < _pathBeginStrings.Length; ++matchTypeIndex)
                    {
                        // Note that specifying StringComparison.Ordinal saves ~30% of the time passed in IndexOf.
                        startMatch = str.IndexOf(_pathBeginStrings[matchTypeIndex], currentSearchIndex, StringComparison.Ordinal);
                        if (startMatch != -1)
                            break;
                    }

                    if (startMatch == -1)
                        break;

                    endMatch = str.IndexOfAny(_pathEndCharacters, startMatch + 1);
                    if (endMatch == -1)
                        break;

                    if (builder == null)
                        builder = new StringBuilder(str.Length + 128);

                    // Append what's before the match
                    if (startMatch - currentSearchIndex > 0)
                        builder.Append(str, currentSearchIndex, startMatch - currentSearchIndex);

                    bool isValidMember = true;
                    int startMatchLength = _pathBeginStrings[matchTypeIndex].Length;
                    int memberStartIndex = startMatch + startMatchLength;
                    for (int i = memberStartIndex; i < endMatch; ++i)
                    {
                        char currentChar = str[i];
                        if (!(currentChar >= 'a' && currentChar <= 'z' ||
                            currentChar >= 'A' && currentChar <= 'Z' ||
                            currentChar >= '0' && currentChar <= '9' ||
                            currentChar == '.' || currentChar == '_' ||
                            currentChar == ':'
                            ))
                        {
                            isValidMember = false;
                        }
                    }

                    // A string is escaped if the _PathBeginStrings/_PathEndStrings char is doubled (ie [[ ]])
                    // Also make sure that matchTypeIndex is a char, not a string
                    bool isEscaped = _pathBeginStrings[matchTypeIndex].Length == 1 &&
                                     memberStartIndex > 1 && endMatch < str.Length - 1 &&
                                     str[memberStartIndex - 2] == str[memberStartIndex - 1] &&
                                     str[endMatch] == str[endMatch + 1];

                    containsEscaped |= isEscaped;

                    if (isValidMember && !isEscaped)
                    {
                        bool throwIfNotFound = fallbackValue == null;

                        string resolveResult;
                        try
                        {
                            resolveResult = GetMemberStringValue(str.Substring(memberStartIndex, endMatch - memberStartIndex), throwIfNotFound) ?? fallbackValue?.ToString();
                        }
                        catch (NotFoundException e)
                        {
                            throw new Error(
                                "Error: {0} in '{1}'\n{2}",
                                e.Message,
                                str,
                                e.Arguments
                            );
                        }

                        if (resolveResult == null)
                        {
                            // Resolve failed.
                            builder.Append(str, startMatch, endMatch - startMatch + 1);
                        }
                        else
                        {
                            ++nbrReplacements;
                            builder.Append(resolveResult);
                        }
                        currentSearchIndex = endMatch + 1;
                    }
                    else
                    {
                        builder.Append(str, startMatch, startMatchLength);
                        currentSearchIndex = startMatch + startMatchLength;
                    }
                }

                if (nbrReplacements == 0 && currentSearchIndex == 0)
                    break;

                builder.Append(str, currentSearchIndex, strLength - currentSearchIndex);
                str = builder.ToString();
                wasChanged = true;
                builder.Clear();

                if (nbrReplacements == 0)
                    break;
            }

            if (!containsEscaped)
                return str;

            // Now that we have done all replace, convert all escaped char.
            foreach (string beginStr in _pathBeginStrings)
            {
                if (beginStr.Length != 1)
                    continue;
                string escapedStr = beginStr + beginStr;
                wasChanged = true;
                str = str.Replace(escapedStr, beginStr);
            }

            foreach (char endChar in _pathEndCharacters)
            {
                string endStr = string.Empty + endChar;
                string escapedStr = endStr + endStr;
                wasChanged = true;
                str = str.Replace(escapedStr, endStr);
            }

            return str;
        }