{"action":"created","comment":{"url":"https://api.github.com/repos/dotnet/corefx/pulls/comments/42827516","id":42827516,"diff_hunk":"@@ -0,0 +1,385 @@\n+// Copyright (c) Microsoft. All rights reserved.\n+// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n+\n+using System.Collections.Generic;\n+using System.Runtime.CompilerServices;\n+\n+namespace System.Runtime.InteropServices\n+{\n+    /// <summary>\n+    /// Native buffer that deals in char size increments. Dispose to free memory. Allows buffers larger\n+    /// than a maximum size string to enable working with very large string arrays.\n+    /// \n+    /// A more performant replacement for StringBuilder when performing native interop.\n+    /// </summary>\n+    /// <remarks>\n+    /// Suggested use through P/Invoke: define DllImport arguments that take a character buffer as IntPtr.\n+    /// NativeStringBuffer has an implicit conversion to IntPtr.\n+    /// </remarks>\n+    internal class StringBuffer : NativeBuffer\n+    {\n+        private ulong _length;\n+\n+        /// <summary>\n+        /// Instantiate the buffer with capacity for at least the specified number of characters. Capacity\n+        /// includes the trailing null character.\n+        /// </summary>\n+        public StringBuffer(ulong initialCapacity = 0)\n+            : base(initialCapacity)\n+        {\n+        }\n+\n+        /// <summary>\n+        /// Instantiate the buffer with a copy of the specified string.\n+        /// </summary>\n+        public unsafe StringBuffer(string initialContents)\n+            : base(0)\n+        {\n+            // We don't pass the count of bytes to the base constructor, appending will\n+            // initialize to the correct size for the specified initial contents.\n+            if (initialContents != null)\n+            {\n+                this.Append(initialContents);\n+            }\n+        }\n+\n+        /// <summary>\n+        /// Get/set the character at the given index.\n+        /// </summary>\n+        /// <exception cref=\"ArgumentOutOfRangeException\">Thrown if attempting to index outside of the buffer length.</exception>\n+        public new unsafe char this[ulong index]\n+        {\n+            get\n+            {\n+                if (index >= _length) throw new ArgumentOutOfRangeException(\"index\");\n+                return CharPointer[index];\n+            }\n+            set\n+            {\n+                if (index >= _length) throw new ArgumentOutOfRangeException(\"index\");\n+                CharPointer[index] = value;\n+            }\n+        }\n+\n+        /// <summary>\n+        /// Character capacity of the buffer. Includes the count for the trailing null character.\n+        /// </summary>\n+        public ulong CharCapacity\n+        {\n+            get\n+            {\n+                ulong byteCapacity = ByteCapacity;\n+                return byteCapacity == 0 ? 0 : byteCapacity / sizeof(char);\n+            }\n+        }\n+\n+        /// <summary>\n+        /// Ensure capacity in characters is at least the given minimum.\n+        /// </summary>\n+        /// <exception cref=\"OutOfMemoryException\">Thrown if unable to allocate memory when setting.</exception>\n+        /// <exception cref=\"ArgumentOutOfRangeException\">Thrown if attempting to set <paramref name=\"Capacity\"/> to a value that is larger than the maximum addressable memory.</exception>\n+        public override void EnsureCapacity(ulong minCapacity)\n+        {\n+            if (minCapacity > (ulong.MaxValue / sizeof(char))) throw new ArgumentOutOfRangeException(\"minCapacity\");\n+            base.EnsureCapacity(minCapacity * sizeof(char));\n+        }\n+\n+        /// <summary>\n+        /// The logical length of the buffer in characters. (Does not include the final null.) Will automatically attempt to increase capacity.\n+        /// This is where the usable data ends.\n+        /// </summary>\n+        /// <exception cref=\"ArgumentOutOfRangeException\">Thrown if attempting to set <paramref name=\"nameof(Length)\"/> to a value that is larger than the maximum addressable memory.</exception>\n+        /// <exception cref=\"OutOfMemoryException\">Thrown if unable to allocate memory when setting.</exception>\n+        public unsafe ulong Length\n+        {\n+            get { return _length; }\n+            set\n+            {\n+                // Null terminate\n+                EnsureCapacity(value + 1);\n+                CharPointer[value] = '\\0';\n+\n+                _length = value;\n+            }\n+        }\n+\n+        /// <summary>\n+        /// For use when the native api null terminates but doesn't return a length.\n+        /// If no null is found, the length will not be changed.\n+        /// </summary>\n+        public unsafe void SetLengthToFirstNull()\n+        {\n+            char* buffer = CharPointer;\n+            ulong capacity = CharCapacity;\n+            for (ulong i = 0; i < capacity; i++)\n+            {\n+                if (buffer[i] == '\\0')\n+                {\n+                    _length = i;\n+                    break;\n+                }\n+            }\n+        }\n+\n+        internal unsafe char* CharPointer\n+        {\n+            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n+            get\n+            {\n+                return (char*)VoidPointer;\n+            }\n+        }\n+\n+        /// <summary>\n+        /// Returns true if the buffer starts with the given string.\n+        /// </summary>\n+        public bool StartsWithOrdinal(string value)\n+        {\n+            if (value == null) throw new ArgumentNullException(\"value\");\n+            if (_length < (ulong)value.Length) return false;\n+            return SubStringEquals(value, startIndex: 0, count: value.Length);\n+        }\n+\n+        /// <summary>\n+        /// Returns true if the specified StringBuffer substring equals the given value.\n+        /// </summary>\n+        /// <param name=\"value\">The value to compare against the specified substring.</param>\n+        /// <param name=\"startIndex\">Start index of the sub string.</param>\n+        /// <param name=\"count\">Length of the substring, or -1 to check all remaining.</param>\n+        /// <exception cref=\"ArgumentOutOfRangeException\">\n+        /// Thrown if <paramref name=\"startIndex\"/> or <paramref name=\"count\"/> are outside the range\n+        /// of the buffer's length.\n+        /// </exception>\n+        public unsafe bool SubStringEquals(string value, ulong startIndex = 0, int count = -1)\n+        {\n+            if (value == null) return false;\n+            if (count < -1) throw new ArgumentOutOfRangeException(\"count\");\n+            ulong realCount = count == -1 ? _length - startIndex : (ulong)count;\n+            if (startIndex + realCount > _length) throw new ArgumentOutOfRangeException(\"count\");\n+\n+            int length = value.Length;\n+\n+            // Check the substring length against the input length\n+            if (realCount != (ulong)length) return false;\n+\n+            fixed (char* valueStart = value)\n+            {\n+                char* bufferStart = CharPointer + startIndex;\n+                for (int i = 0; i < length; i++)\n+                {\n+                    if (*bufferStart++ != valueStart[i]) return false;\n+                }\n+            }\n+\n+            return true;\n+        }\n+\n+        /// <summary>\n+        /// Append the given string.\n+        /// </summary>\n+        /// <param name=\"value\">The string to append.</param>\n+        /// <param name=\"startIndex\">The index in the input string to start appending from.</param>\n+        /// <param name=\"count\">The count of characters to copy from the input string, or -1 for all remaining.</param>\n+        /// <exception cref=\"ArgumentNullException\">Thrown if <paramref name=\"value\"/> is null.</exception>\n+        /// <exception cref=\"ArgumentOutOfRangeException\">\n+        /// Thrown if <paramref name=\"startIndex\"/> or <paramref name=\"count\"/> are outside the range\n+        /// of <paramref name=\"value\"/> characters.\n+        /// </exception>\n+        public unsafe void Append(string value, int startIndex = 0, int count = -1)\n+        {\n+            this.CopyFrom(\n+                bufferIndex: _length,\n+                source: value,\n+                sourceIndex: startIndex,\n+                count: count);\n+        }\n+\n+        /// <summary>\n+        /// Append the given buffer.\n+        /// </summary>\n+        /// <param name=\"value\">The buffer to append.</param>\n+        /// <param name=\"startIndex\">The index in the input buffer to start appending from.</param>\n+        /// <param name=\"count\">The count of characters to copy from the buffer string.</param>\n+        /// <exception cref=\"ArgumentNullException\">Thrown if <paramref name=\"value\"/> is null.</exception>\n+        /// <exception cref=\"ArgumentOutOfRangeException\">\n+        /// Thrown if <paramref name=\"startIndex\"/> or <paramref name=\"count\"/> are outside the range\n+        /// of <paramref name=\"value\"/> characters.\n+        /// </exception>\n+        public unsafe void Append(StringBuffer value, ulong startIndex = 0, ulong count = 0)\n+        {\n+            if (value == null) throw new ArgumentNullException(\"value\");\n+            if (count == 0) return;\n+            value.CopyTo(\n+                bufferIndex: startIndex,\n+                destination: this,\n+                destinationIndex: _length,\n+                count: count);\n+        }\n+\n+        /// <summary>\n+        /// Copy contents to the specified buffer. Destination index must be within current destination length.\n+        /// Will grow the destination buffer if needed.\n+        /// </summary>\n+        public unsafe void CopyTo(ulong bufferIndex, StringBuffer destination, ulong destinationIndex, ulong count)\n+        {\n+            if (destination == null) throw new ArgumentNullException(\"destination\");\n+            if (destinationIndex > destination._length) throw new ArgumentOutOfRangeException(\"destinationIndex\");\n+            if (_length < bufferIndex + count) throw new ArgumentOutOfRangeException(\"count\");\n+\n+            if (count == 0) return;\n+            ulong lastIndex = destinationIndex + (ulong)count;\n+            if (destination._length < lastIndex) destination.Length = lastIndex;\n+\n+            Buffer.MemoryCopy(\n+                source: CharPointer + bufferIndex,\n+                destination: destination.CharPointer + destinationIndex,\n+                destinationSizeInBytes: checked((long)destination.ByteCapacity * sizeof(char)),\n+                sourceBytesToCopy: checked((long)count * sizeof(char)));\n+        }\n+\n+        /// <summary>\n+        /// Copy contents from the specified string into the buffer at the given index. Start index must be within the current length of\n+        /// the buffer, will grow as necessary.\n+        /// </summary>\n+        public unsafe void CopyFrom(ulong bufferIndex, string source, int sourceIndex = 0, int count = -1)\n+        {\n+            if (source == null) throw new ArgumentNullException(\"source\");\n+            if (bufferIndex > _length) throw new ArgumentOutOfRangeException(\"bufferIndex\");\n+            if (sourceIndex < 0 || sourceIndex > source.Length) throw new ArgumentOutOfRangeException(\"sourceIndex\");\n+            if (count < 0) count = source.Length - sourceIndex;\n+            if (source.Length < sourceIndex + count) throw new ArgumentOutOfRangeException(\"count\");\n+\n+            if (count == 0) return;\n+            ulong lastIndex = bufferIndex + (ulong)count;\n+            if (_length < lastIndex) Length = lastIndex;\n+\n+            fixed (char* content = source)\n+            {\n+                Buffer.MemoryCopy(\n+                    source: content + sourceIndex,\n+                    destination: CharPointer + bufferIndex,\n+                    destinationSizeInBytes: checked((long)ByteCapacity),\n+                    sourceBytesToCopy: count * sizeof(char));\n+            }\n+        }\n+\n+        /// <summary>\n+        /// Split the contents into strings via the given split characters.\n+        /// </summary>\n+        /// <exception cref=\"OverflowException\">Thrown if the substring is too big to fit in a string.</exception>\n+        unsafe public IEnumerable<string> Split(char splitCharacter)\n+        {\n+            var strings = new List<string>();\n+            char* start = CharPointer;\n+            char* current = start;\n+\n+            ulong length = _length;\n+\n+            for (ulong i = 0; i < length; i++)\n+            {\n+                if (splitCharacter == *current)\n+                {\n+                    // Split\n+                    strings.Add(new string(value: start, startIndex: 0, length: checked((int)(current - start))));\n+                    start = current + 1;\n+                }\n+\n+                current++;\n+            }\n+\n+            strings.Add(new string(value: start, startIndex: 0, length: checked((int)(current - start))));\n+\n+            return strings;\n+        }\n+\n+        /// <summary>\n+        /// True if the buffer contains the given character.\n+        /// </summary>\n+        public unsafe bool Contains(char value)\n+        {\n+            char* start = CharPointer;\n+            ulong length = _length;\n+\n+            for (ulong i = 0; i < length; i++)\n+            {\n+                if (*start++ == value) return true;\n+            }\n+\n+            return false;\n+        }\n+\n+        /// <summary>\n+        /// True if the buffer contains any of the specified characters.\n+        /// </summary>\n+        public unsafe bool Contains(params char[] values)\n+        {\n+            if (values == null || values.Length == 0) return false;\n+\n+            char* start = CharPointer;\n+            ulong length = _length;\n+\n+            for (ulong i = 0; i < length; i++)\n+            {\n+                if (ContainsChar(values, *start)) return true;\n+                start++;\n+            }\n+\n+            return false;\n+        }\n+\n+        /// <summary>\n+        /// Trim the specified values from the end of the buffer.\n+        /// </summary>\n+        public unsafe void TrimEnd(params char[] values)\n+        {\n+            if (values == null || values.Length == 0 || _length == 0) return;\n+\n+            char* end = CharPointer + _length - 1;\n+\n+            while (ContainsChar(values, *end))\n+            {\n+                Length--;\n+                end--;\n+            }\n+        }\n+\n+        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n+        private static bool ContainsChar(char[] source, char value)\n+        {\n+            for (int i = 0; i < source.Length; i++)\n+            {\n+                if (value == source[i]) return true;\n+            }\n+            return false;\n+        }\n+\n+        /// <summary>\n+        /// String representation of the entire buffer. If the buffer is larger than the maximum size string (int.MaxValue) will truncate.\n+        /// </summary>\n+        public unsafe override string ToString()\n+        {\n+            if (_length == 0) return string.Empty;\n+            return new string(CharPointer, startIndex: 0, length: _length > int.MaxValue ? int.MaxValue : checked((int)_length));\n+        }\n+\n+        /// <summary>\n+        /// Get the given substring in the buffer.\n+        /// </summary>\n+        /// <param name=\"count\">Count of characters to take, or remaining characters from <paramref name=\"startIndex\"/> if -1.</param>\n+        /// <exception cref=\"ArgumentOutOfRangeException\">\n+        /// Thrown if <paramref name=\"startIndex\"/> or <paramref name=\"count\"/> are outside the range of the buffer's length\n+        /// or count is greater than the maximum string size (int.MaxValue).\n+        /// </exception>\n+        public unsafe string SubString(ulong startIndex, int count = -1)","path":"src/Common/src/System/Runtime/InteropServices/StringBuffer.cs","position":373,"original_position":373,"commit_id":"384bc2a55895248e3ec4781cae9946549e8eceaf","original_commit_id":"384bc2a55895248e3ec4781cae9946549e8eceaf","user":{"login":"stephentoub","id":2642209,"avatar_url":"https://avatars.githubusercontent.com/u/2642209?v=3","gravatar_id":"","url":"https://api.github.com/users/stephentoub","html_url":"https://github.com/stephentoub","followers_url":"https://api.github.com/users/stephentoub/followers","following_url":"https://api.github.com/users/stephentoub/following{/other_user}","gists_url":"https://api.github.com/users/stephentoub/gists{/gist_id}","starred_url":"https://api.github.com/users/stephentoub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephentoub/subscriptions","organizations_url":"https://api.github.com/users/stephentoub/orgs","repos_url":"https://api.github.com/users/stephentoub/repos","events_url":"https://api.github.com/users/stephentoub/events{/privacy}","received_events_url":"https://api.github.com/users/stephentoub/received_events","type":"User","site_admin":false},"body":"Different capitalization than string.Substring","created_at":"2015-10-23T02:10:46Z","updated_at":"2015-10-23T02:10:46Z","html_url":"https://github.com/dotnet/corefx/pull/3992#discussion_r42827516","pull_request_url":"https://api.github.com/repos/dotnet/corefx/pulls/3992","_links":{"self":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/comments/42827516"},"html":{"href":"https://github.com/dotnet/corefx/pull/3992#discussion_r42827516"},"pull_request":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/3992"}}},"pull_request":{"url":"https://api.github.com/repos/dotnet/corefx/pulls/3992","id":48236079,"html_url":"https://github.com/dotnet/corefx/pull/3992","diff_url":"https://github.com/dotnet/corefx/pull/3992.diff","patch_url":"https://github.com/dotnet/corefx/pull/3992.patch","issue_url":"https://api.github.com/repos/dotnet/corefx/issues/3992","number":3992,"state":"open","locked":false,"title":"Avoid StringBuilder interop perf","user":{"login":"JeremyKuhne","id":8184940,"avatar_url":"https://avatars.githubusercontent.com/u/8184940?v=3","gravatar_id":"","url":"https://api.github.com/users/JeremyKuhne","html_url":"https://github.com/JeremyKuhne","followers_url":"https://api.github.com/users/JeremyKuhne/followers","following_url":"https://api.github.com/users/JeremyKuhne/following{/other_user}","gists_url":"https://api.github.com/users/JeremyKuhne/gists{/gist_id}","starred_url":"https://api.github.com/users/JeremyKuhne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JeremyKuhne/subscriptions","organizations_url":"https://api.github.com/users/JeremyKuhne/orgs","repos_url":"https://api.github.com/users/JeremyKuhne/repos","events_url":"https://api.github.com/users/JeremyKuhne/events{/privacy}","received_events_url":"https://api.github.com/users/JeremyKuhne/received_events","type":"User","site_admin":false},"body":"Creates an internal buffer specifically for interop purposes (NativeBuffer/StringBuffer).\r\nCaching is implicit, disposing will return the buffer to the cache immediately.\r\nBuffers resize implicitly and utilize new (non depreciated) heap APIs (which handle content\r\ncopying if needed). Buffers do not zero memory for added perf.\r\nStringBuffer can copy directly with strings and other StringBuffers.\r\n\r\nSome StringBuilder perf/functionality issues for interop:\r\n- Does not pin, but could if unchunked (creating 4x allocations for out strings with P/Invoke)\r\n- Does not allow fast copying between StringBuilders\r\n- Does not allow indexing in to skip characters with P/Invoke (char* + offset)\r\n- Cannot compare substrings without allocating or walking char indexing\r\n- Difficult to split null separated string arrays (common in Win32)\r\n- Capacity is actually +1 (doesn't include the null), most Win32 APIs want count + null\r\n\r\nStart moving String/StringBuilder/StringBuffer path internal helper methods to use core\r\nchar* helper for longer methods. Keep StringBuffer overloads in a separate file to\r\nallow inclusion just with interoping projects.","created_at":"2015-10-20T18:02:34Z","updated_at":"2015-10-23T02:10:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9bf80bc11be86112016d2ee26429257ef8731dd5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/dotnet/corefx/pulls/3992/commits","review_comments_url":"https://api.github.com/repos/dotnet/corefx/pulls/3992/comments","review_comment_url":"https://api.github.com/repos/dotnet/corefx/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dotnet/corefx/issues/3992/comments","statuses_url":"https://api.github.com/repos/dotnet/corefx/statuses/384bc2a55895248e3ec4781cae9946549e8eceaf","head":{"label":"JeremyKuhne:StringBuffer","ref":"StringBuffer","sha":"384bc2a55895248e3ec4781cae9946549e8eceaf","user":{"login":"JeremyKuhne","id":8184940,"avatar_url":"https://avatars.githubusercontent.com/u/8184940?v=3","gravatar_id":"","url":"https://api.github.com/users/JeremyKuhne","html_url":"https://github.com/JeremyKuhne","followers_url":"https://api.github.com/users/JeremyKuhne/followers","following_url":"https://api.github.com/users/JeremyKuhne/following{/other_user}","gists_url":"https://api.github.com/users/JeremyKuhne/gists{/gist_id}","starred_url":"https://api.github.com/users/JeremyKuhne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JeremyKuhne/subscriptions","organizations_url":"https://api.github.com/users/JeremyKuhne/orgs","repos_url":"https://api.github.com/users/JeremyKuhne/repos","events_url":"https://api.github.com/users/JeremyKuhne/events{/privacy}","received_events_url":"https://api.github.com/users/JeremyKuhne/received_events","type":"User","site_admin":false},"repo":{"id":30339123,"name":"corefx","full_name":"JeremyKuhne/corefx","owner":{"login":"JeremyKuhne","id":8184940,"avatar_url":"https://avatars.githubusercontent.com/u/8184940?v=3","gravatar_id":"","url":"https://api.github.com/users/JeremyKuhne","html_url":"https://github.com/JeremyKuhne","followers_url":"https://api.github.com/users/JeremyKuhne/followers","following_url":"https://api.github.com/users/JeremyKuhne/following{/other_user}","gists_url":"https://api.github.com/users/JeremyKuhne/gists{/gist_id}","starred_url":"https://api.github.com/users/JeremyKuhne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JeremyKuhne/subscriptions","organizations_url":"https://api.github.com/users/JeremyKuhne/orgs","repos_url":"https://api.github.com/users/JeremyKuhne/repos","events_url":"https://api.github.com/users/JeremyKuhne/events{/privacy}","received_events_url":"https://api.github.com/users/JeremyKuhne/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/JeremyKuhne/corefx","description":"This repo contains the foundational libraries that make up the .NET Core development stack.","fork":true,"url":"https://api.github.com/repos/JeremyKuhne/corefx","forks_url":"https://api.github.com/repos/JeremyKuhne/corefx/forks","keys_url":"https://api.github.com/repos/JeremyKuhne/corefx/keys{/key_id}","collaborators_url":"https://api.github.com/repos/JeremyKuhne/corefx/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/JeremyKuhne/corefx/teams","hooks_url":"https://api.github.com/repos/JeremyKuhne/corefx/hooks","issue_events_url":"https://api.github.com/repos/JeremyKuhne/corefx/issues/events{/number}","events_url":"https://api.github.com/repos/JeremyKuhne/corefx/events","assignees_url":"https://api.github.com/repos/JeremyKuhne/corefx/assignees{/user}","branches_url":"https://api.github.com/repos/JeremyKuhne/corefx/branches{/branch}","tags_url":"https://api.github.com/repos/JeremyKuhne/corefx/tags","blobs_url":"https://api.github.com/repos/JeremyKuhne/corefx/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/JeremyKuhne/corefx/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/JeremyKuhne/corefx/git/refs{/sha}","trees_url":"https://api.github.com/repos/JeremyKuhne/corefx/git/trees{/sha}","statuses_url":"https://api.github.com/repos/JeremyKuhne/corefx/statuses/{sha}","languages_url":"https://api.github.com/repos/JeremyKuhne/corefx/languages","stargazers_url":"https://api.github.com/repos/JeremyKuhne/corefx/stargazers","contributors_url":"https://api.github.com/repos/JeremyKuhne/corefx/contributors","subscribers_url":"https://api.github.com/repos/JeremyKuhne/corefx/subscribers","subscription_url":"https://api.github.com/repos/JeremyKuhne/corefx/subscription","commits_url":"https://api.github.com/repos/JeremyKuhne/corefx/commits{/sha}","git_commits_url":"https://api.github.com/repos/JeremyKuhne/corefx/git/commits{/sha}","comments_url":"https://api.github.com/repos/JeremyKuhne/corefx/comments{/number}","issue_comment_url":"https://api.github.com/repos/JeremyKuhne/corefx/issues/comments{/number}","contents_url":"https://api.github.com/repos/JeremyKuhne/corefx/contents/{+path}","compare_url":"https://api.github.com/repos/JeremyKuhne/corefx/compare/{base}...{head}","merges_url":"https://api.github.com/repos/JeremyKuhne/corefx/merges","archive_url":"https://api.github.com/repos/JeremyKuhne/corefx/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/JeremyKuhne/corefx/downloads","issues_url":"https://api.github.com/repos/JeremyKuhne/corefx/issues{/number}","pulls_url":"https://api.github.com/repos/JeremyKuhne/corefx/pulls{/number}","milestones_url":"https://api.github.com/repos/JeremyKuhne/corefx/milestones{/number}","notifications_url":"https://api.github.com/repos/JeremyKuhne/corefx/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/JeremyKuhne/corefx/labels{/name}","releases_url":"https://api.github.com/repos/JeremyKuhne/corefx/releases{/id}","created_at":"2015-02-05T05:16:58Z","updated_at":"2015-05-08T20:58:22Z","pushed_at":"2015-10-22T22:48:36Z","git_url":"git://github.com/JeremyKuhne/corefx.git","ssh_url":"git@github.com:JeremyKuhne/corefx.git","clone_url":"https://github.com/JeremyKuhne/corefx.git","svn_url":"https://github.com/JeremyKuhne/corefx","homepage":"","size":36662,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"dotnet:master","ref":"master","sha":"71dff92c0a4960ebe452bd72649f678b84a83dde","user":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"repo":{"id":26295345,"name":"corefx","full_name":"dotnet/corefx","owner":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dotnet/corefx","description":"This repo contains the .NET Core foundational libraries, called CoreFX. It includes classes for collections, file systems, console, XML, async and many others.","fork":false,"url":"https://api.github.com/repos/dotnet/corefx","forks_url":"https://api.github.com/repos/dotnet/corefx/forks","keys_url":"https://api.github.com/repos/dotnet/corefx/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dotnet/corefx/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dotnet/corefx/teams","hooks_url":"https://api.github.com/repos/dotnet/corefx/hooks","issue_events_url":"https://api.github.com/repos/dotnet/corefx/issues/events{/number}","events_url":"https://api.github.com/repos/dotnet/corefx/events","assignees_url":"https://api.github.com/repos/dotnet/corefx/assignees{/user}","branches_url":"https://api.github.com/repos/dotnet/corefx/branches{/branch}","tags_url":"https://api.github.com/repos/dotnet/corefx/tags","blobs_url":"https://api.github.com/repos/dotnet/corefx/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dotnet/corefx/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dotnet/corefx/git/refs{/sha}","trees_url":"https://api.github.com/repos/dotnet/corefx/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dotnet/corefx/statuses/{sha}","languages_url":"https://api.github.com/repos/dotnet/corefx/languages","stargazers_url":"https://api.github.com/repos/dotnet/corefx/stargazers","contributors_url":"https://api.github.com/repos/dotnet/corefx/contributors","subscribers_url":"https://api.github.com/repos/dotnet/corefx/subscribers","subscription_url":"https://api.github.com/repos/dotnet/corefx/subscription","commits_url":"https://api.github.com/repos/dotnet/corefx/commits{/sha}","git_commits_url":"https://api.github.com/repos/dotnet/corefx/git/commits{/sha}","comments_url":"https://api.github.com/repos/dotnet/corefx/comments{/number}","issue_comment_url":"https://api.github.com/repos/dotnet/corefx/issues/comments{/number}","contents_url":"https://api.github.com/repos/dotnet/corefx/contents/{+path}","compare_url":"https://api.github.com/repos/dotnet/corefx/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dotnet/corefx/merges","archive_url":"https://api.github.com/repos/dotnet/corefx/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dotnet/corefx/downloads","issues_url":"https://api.github.com/repos/dotnet/corefx/issues{/number}","pulls_url":"https://api.github.com/repos/dotnet/corefx/pulls{/number}","milestones_url":"https://api.github.com/repos/dotnet/corefx/milestones{/number}","notifications_url":"https://api.github.com/repos/dotnet/corefx/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dotnet/corefx/labels{/name}","releases_url":"https://api.github.com/repos/dotnet/corefx/releases{/id}","created_at":"2014-11-06T23:42:48Z","updated_at":"2015-10-23T00:21:42Z","pushed_at":"2015-10-23T00:23:07Z","git_url":"git://github.com/dotnet/corefx.git","ssh_url":"git@github.com:dotnet/corefx.git","clone_url":"https://github.com/dotnet/corefx.git","svn_url":"https://github.com/dotnet/corefx","homepage":"http://dotnet.github.io/core/","size":85499,"stargazers_count":8480,"watchers_count":8480,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1857,"mirror_url":null,"open_issues_count":672,"forks":1857,"open_issues":672,"watchers":8480,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/3992"},"html":{"href":"https://github.com/dotnet/corefx/pull/3992"},"issue":{"href":"https://api.github.com/repos/dotnet/corefx/issues/3992"},"comments":{"href":"https://api.github.com/repos/dotnet/corefx/issues/3992/comments"},"review_comments":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/3992/comments"},"review_comment":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/3992/commits"},"statuses":{"href":"https://api.github.com/repos/dotnet/corefx/statuses/384bc2a55895248e3ec4781cae9946549e8eceaf"}}}}