/// <summary>
        /// Reads until the specified <paramref name="keychar" /> is encountered. <paramref name="keychar" /> will not be included in the returned string.
        /// </summary>
        /// <param name="reader">A <see cref="TextReader" /> object.</param>
        /// <param name="keychar">The <paramref name="reader" /> will advance its position to the character immediately after the next occurrence of this <paramref name="keychar" />.</param>
        /// <param name="returnIfKeycharNotFound"><c>true</c> if a string starting from the reader's current position to the end should be returned if no <paramref name="keychar"/> is encountered in reading; <c>false</c> if <c>null</c> should be returned in this situation.</param>
        /// <returns>A <see cref="string" /> read from the <see cref="TextReader" /> from its current position to the position of the specified <paramref name="keychar" />, or to the end of the <paramref name="reader"/> if no such <paramref name="keychar"/> is found.</returns>
        public static string ReadTo(this TextReader reader, char keychar, bool returnIfKeycharNotFound = true)
        {
            var sb = StringBuilderCache.Acquire();
            int ci;

            while ((ci = reader.Read()) != -1)
            {
                if (ci == keychar)
                {
                    return(StringBuilderCache.GetStringAndRelease(sb));
                }
                else
                {
                    sb.Append((char)ci);
                }
            }

            if (returnIfKeycharNotFound)
            {
                return(StringBuilderCache.GetStringAndRelease(sb));
            }
            else
            {
                StringBuilderCache.Release(sb);
                return(null);
            }
        }
        /// <summary>
        /// Reads until the specified <paramref name="keyword" /> is encountered. <paramref name="keyword" /> will be included at the end of the returned string.
        /// </summary>
        /// <param name="reader">A <see cref="TextReader" /> object.</param>
        /// <param name="keyword">The <paramref name="reader" /> will advance its position to the character immediately after the next occurrence of this <paramref name="keyword" />.</param>
        /// <param name="returnIfKeywordNotFound"><c>true</c> if a string starting from the reader's current position to the end should be returned if no <paramref name="keyword"/> is encountered in reading; <c>false</c> if <c>null</c> should be returned in this situation.</param>
        /// <returns>A <see cref="string" /> read from the <see cref="TextReader" /> from its current position to the position of the specified <paramref name="keyword" /> with <paramref name="keyword"/> at the end of the returned <see cref="string"/>, or to the end of the <paramref name="reader"/> if no such <paramref name="keyword"/> is found.</returns>
        public static string ReadAfter(this TextReader reader, string keyword, bool returnIfKeywordNotFound = true)
        {
            var i = 0;
            int ci;
            var sb = StringBuilderCache.Acquire();

            while ((ci = reader.Read()) != -1)
            {
                var c = (char)ci;
                if (c == keyword[i])
                {
                    ++i;
                    if (i == keyword.Length)
                    {
                        sb.Append(keyword);
                        return(StringBuilderCache.GetStringAndRelease(sb));
                    }
                }
                else
                {
                    if (i != 0)
                    {
                        sb.Append(keyword.Substring(0, i));
                        i = 0;
                    }

                    if (c == keyword[0])
                    {
                        ++i;
                    }
                    else
                    {
                        sb.Append(c);
                    }
                }
            }

            if (returnIfKeywordNotFound)
            {
                return(StringBuilderCache.GetStringAndRelease(sb));
            }
            else
            {
                StringBuilderCache.Release(sb);
                return(null);
            }
        }
Exemple #3
0
        private static async Task <string> InternalReadAllTextAsync(string path, Encoding encoding, CancellationToken cancellationToken)
        {
            Debug.Assert(!string.IsNullOrEmpty(path));
            Debug.Assert(encoding != null);

            char[]        buffer = null;
            StringBuilder sb     = null;
            StreamReader  sr     = AsyncStreamReader(path, encoding);

            try
            {
                cancellationToken.ThrowIfCancellationRequested();
                sb     = StringBuilderCache.Acquire();
                buffer = ArrayPool <char> .Shared.Rent(sr.CurrentEncoding.GetMaxCharCount(DefaultBufferSize));

                for (;;)
                {
                    int read = await sr.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);

                    if (read == 0)
                    {
                        return(sb.ToString());
                    }

                    sb.Append(buffer, 0, read);
                    cancellationToken.ThrowIfCancellationRequested();
                }
            }
            finally
            {
                sr.Dispose();
                if (buffer != null)
                {
                    ArrayPool <char> .Shared.Return(buffer);
                }

                if (sb != null)
                {
                    StringBuilderCache.Release(sb);
                }
            }
        }
Exemple #4
0
        private void WriteFormatHelper(string format, ParamsArray args, bool appendNewLine)
        {
            StringBuilder sb =
                StringBuilderCache.Acquire((format?.Length ?? 0) + args.Length * 8)
                .AppendFormatHelper(null, format !, args); // AppendFormatHelper will appropriately throw ArgumentNullException for a null format

            StringBuilder.ChunkEnumerator chunks = sb.GetChunks();

            bool more = chunks.MoveNext();

            while (more)
            {
                ReadOnlySpan <char> current = chunks.Current.Span;
                more = chunks.MoveNext();

                // If final chunk, include the newline if needed
                WriteSpan(current, appendNewLine: more?false: appendNewLine);
            }

            StringBuilderCache.Release(sb);
        }
Exemple #5
0
        public override string GetCurrentDirectory()
        {
            StringBuilder sb = StringBuilderCache.Acquire(Interop.mincore.MAX_PATH + 1);

            if (Interop.mincore.GetCurrentDirectory(sb.Capacity, sb) == 0)
            {
                throw Win32Marshal.GetExceptionForLastWin32Error();
            }
            String currentDirectory = sb.ToString();

            // Note that if we have somehow put our command prompt into short
            // file name mode (ie, by running edlin or a DOS grep, etc), then
            // this will return a short file name.
            if (currentDirectory.IndexOf('~') >= 0)
            {
                int r = Interop.mincore.GetLongPathName(currentDirectory, sb, sb.Capacity);
                if (r == 0 || r >= Interop.mincore.MAX_PATH)
                {
                    int errorCode = Marshal.GetLastWin32Error();
                    if (r >= Interop.mincore.MAX_PATH)
                    {
                        errorCode = Interop.mincore.Errors.ERROR_FILENAME_EXCED_RANGE;
                    }
                    if (errorCode != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND &&
                        errorCode != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND &&
                        errorCode != Interop.mincore.Errors.ERROR_INVALID_FUNCTION &&  // by design - enough said.
                        errorCode != Interop.mincore.Errors.ERROR_ACCESS_DENIED)
                    {
                        throw Win32Marshal.GetExceptionForWin32Error(errorCode);
                    }
                }
                currentDirectory = sb.ToString();
            }
            StringBuilderCache.Release(sb);

            return(currentDirectory);
        }
Exemple #6
0
        private static string NormalizePath(
            string path, bool fullCheck,
            int maxPathLength, bool expandShortPaths) // ignored on Unix
        {
            Debug.Assert(path != null);

            if (path.Length == 0)
            {
                throw new ArgumentException(SR.Arg_PathIllegal);
            }

            if (fullCheck)
            {
                PathInternal.CheckInvalidPathChars(path);

                // Expand with current directory if necessary
                if (!IsPathRooted(path))
                {
                    path = Combine(Interop.libc.getcwd(), path);
                }
            }

            // Remove "//", "/./", and "/../" from the path.  We would ideally use realpath
            // to do this, but it resolves symlinks, requires that the file actually exist,
            // and turns it into a full path, which we only want if fullCheck is true.
            // Instead, we do the normalization manually, copying each character to the output,
            // except the ones we're removing, such that the builder contains the normalized path
            // at the end.
            var sb = StringBuilderCache.Acquire(path.Length);
            int componentCharCount = 0;

            for (int i = 0; i < path.Length; i++)
            {
                char c = path[i];

                if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length)
                {
                    componentCharCount = 0;

                    // Skip this character if it's a directory separator and if the next character is, too,
                    // e.g. "parent//child" => "parent/child"
                    if (PathInternal.IsDirectorySeparator(path[i + 1]))
                    {
                        continue;
                    }

                    // Skip this character and the next if it's referring to the current directory,
                    // e.g. "parent/./child" =? "parent/child"
                    if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) &&
                        path[i + 1] == '.')
                    {
                        i++;
                        continue;
                    }

                    // Skip this character and the next two if it's referring to the parent directory,
                    // e.g. "parent/child/../grandchild" => "parent/grandchild"
                    if (i + 2 < path.Length &&
                        (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) &&
                        path[i + 1] == '.' && path[i + 2] == '.')
                    {
                        // Unwind back to the last slash (and if there isn't one, clear out everything).
                        int s;
                        for (s = sb.Length - 1; s >= 0; s--)
                        {
                            if (PathInternal.IsDirectorySeparator(sb[s]))
                            {
                                sb.Length = s;
                                break;
                            }
                        }
                        if (s < 0)
                        {
                            sb.Length = 0;
                        }

                        i += 2;
                        continue;
                    }
                }

                if (++componentCharCount > MaxComponentLength)
                {
                    throw new PathTooLongException(SR.IO_PathTooLong);
                }
                sb.Append(c);
            }

            Debug.Assert(sb.Length < path.Length || sb.ToString() == path,
                         "Either we've removed characters, or the string should be unmodified from the input path.");

            if (sb.Length > MaxPath)
            {
                throw new PathTooLongException(SR.IO_PathTooLong);
            }

            string result =
                sb.Length == 0 ? (fullCheck ? DirectorySeparatorCharAsString : string.Empty) :
                sb.Length == path.Length ? path :
                sb.ToString();

            StringBuilderCache.Release(sb);
            return(result);
        }
        // We rely on Windows to remove relative segments on Windows. This would need to be updated to
        // handle the proper rooting on Windows if we for some reason need it.

        /// <summary>
        /// Try to remove relative segments from the given path (without combining with a root).
        /// </summary>
        /// <param name="skip">Skip the specified number of characters before evaluating.</param>
        internal static string RemoveRelativeSegments(string path, int skip = 0)
        {
            bool flippedSeparator = false;

            // Remove "//", "/./", and "/../" from the path by copying each character to the output,
            // except the ones we're removing, such that the builder contains the normalized path
            // at the end.
            var sb = StringBuilderCache.Acquire(path.Length);

            if (skip > 0)
            {
                sb.Append(path, 0, skip);
            }

            int componentCharCount = 0;

            for (int i = skip; i < path.Length; i++)
            {
                char c = path[i];

                if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length)
                {
                    componentCharCount = 0;

                    // Skip this character if it's a directory separator and if the next character is, too,
                    // e.g. "parent//child" => "parent/child"
                    if (PathInternal.IsDirectorySeparator(path[i + 1]))
                    {
                        continue;
                    }

                    // Skip this character and the next if it's referring to the current directory,
                    // e.g. "parent/./child" =? "parent/child"
                    if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) &&
                        path[i + 1] == '.')
                    {
                        i++;
                        continue;
                    }

                    // Skip this character and the next two if it's referring to the parent directory,
                    // e.g. "parent/child/../grandchild" => "parent/grandchild"
                    if (i + 2 < path.Length &&
                        (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) &&
                        path[i + 1] == '.' && path[i + 2] == '.')
                    {
                        // Unwind back to the last slash (and if there isn't one, clear out everything).
                        int s;
                        for (s = sb.Length - 1; s >= 0; s--)
                        {
                            if (PathInternal.IsDirectorySeparator(sb[s]))
                            {
                                sb.Length = s;
                                break;
                            }
                        }
                        if (s < 0)
                        {
                            sb.Length = 0;
                        }

                        i += 2;
                        continue;
                    }
                }

                if (++componentCharCount > PathInternal.MaxComponentLength)
                {
                    throw new PathTooLongException();
                }

                // Normalize the directory separator if needed
                if (c != Path.DirectorySeparatorChar && c == Path.AltDirectorySeparatorChar)
                {
                    c = Path.DirectorySeparatorChar;
                    flippedSeparator = true;
                }

                sb.Append(c);
            }

            if (flippedSeparator || sb.Length != path.Length)
            {
                return(StringBuilderCache.GetStringAndRelease(sb));
            }
            else
            {
                // We haven't changed the source path, return the original
                StringBuilderCache.Release(sb);
                return(path);
            }
        }
        static string _innerReadToNewlineDelimiter(this TextReader reader, string keyword, bool returnIfKeywordNotFound)
        {
            var  i = 0;
            var  j = 0;
            int  ci;
            var  sb        = StringBuilderCache.Acquire();
            var  delimiter = Environment.NewLine;
            bool secondHit = false;

            while ((ci = reader.Read()) != -1)
            {
                var c = (char)ci;
                if (c == delimiter[j])
                {
                    ++j;
                    if (j == delimiter.Length)
                    {
                        if (secondHit)
                        {
                            break;
                        }
                        else
                        {
                            while ((ci = reader.Read()) != -1 && ci != delimiter[0] && ((char)ci).IsWhiteSpace())
                            {
                                ;
                            }
                            if (ci == -1)
                            {
                                break;
                            }
                            else if (ci == delimiter[0])
                            {
                                secondHit = true;
                                j         = 1;
                                continue;
                            }
                            else
                            {
                                c = (char)ci;
                            }
                        }
                    }
                }
                else if (c == delimiter.Last())
                {
                    while ((ci = reader.Read()) != -1 && ci != delimiter[0] && ((char)ci).IsWhiteSpace())
                    {
                        ;
                    }
                    if (ci == -1)
                    {
                        break;
                    }
                    else if (ci == delimiter[0])
                    {
                        secondHit = true;
                        j         = 1;
                        continue;
                    }
                    else
                    {
                        c = (char)ci;
                    }
                }
                else
                {
                    if (c == delimiter[0])
                    {
                        j = 1;
                    }
                    else
                    {
                        j = 0;
                    }
                }

                if (c == keyword[i])
                {
                    ++i;
                    if (i == keyword.Length)
                    {
                        return(StringBuilderCache.GetStringAndRelease(sb));
                    }
                }
                else
                {
                    if (i != 0)
                    {
                        sb.Append(keyword.Substring(0, i));
                        i = 0;
                    }

                    if (c == keyword[0])
                    {
                        ++i;
                    }
                    else
                    {
                        sb.Append(c);
                    }
                }
            }

            if (returnIfKeywordNotFound)
            {
                return(StringBuilderCache.GetStringAndRelease(sb));
            }
            else
            {
                StringBuilderCache.Release(sb);
                return(null);
            }
        }
        public static string ReadTo(this TextReader reader, string keyword, string delimiter, bool returnIfKeywordNotFound = false)
        {
            if (delimiter == Environment.NewLine)
            {
                return(_innerReadToNewlineDelimiter(reader, keyword, returnIfKeywordNotFound));
            }
            var i = 0;
            var j = 0;
            int ci;
            var sb = StringBuilderCache.Acquire();

            while ((ci = reader.Read()) != -1)
            {
                var c = (char)ci;

                if (c == delimiter[j])
                {
                    ++j;
                    if (j == delimiter.Length)
                    {
                        break;
                    }
                }
                else
                {
                    if (c == delimiter[0])
                    {
                        j = 1;
                    }
                    else
                    {
                        j = 0;
                    }
                }

                if (c == keyword[i])
                {
                    ++i;
                    if (i == keyword.Length)
                    {
                        return(StringBuilderCache.GetStringAndRelease(sb));
                    }
                }
                else
                {
                    if (i != 0)
                    {
                        sb.Append(keyword.Substring(0, i));
                        i = 0;
                    }

                    if (c == keyword[0])
                    {
                        ++i;
                    }
                    else
                    {
                        sb.Append(c);
                    }
                }
            }

            if (returnIfKeywordNotFound)
            {
                return(StringBuilderCache.GetStringAndRelease(sb));
            }
            else
            {
                StringBuilderCache.Release(sb);
                return(null);
            }
        }