@@ -716,35 +716,48 @@ internal static void SetMode(ConsoleHandle consoleHandle, ConsoleModes mode)
716716 /// </summary>
717717 /// <param name="consoleHandle"></param>
718718 /// Handle to the console device returned by GetInputHandle
719- /// <param name="initialContent">
720- /// Initial contents of the edit buffer, if any. charactersToRead should be at least as large as the length of this string.
719+ /// <param name="initialContentLength">
720+ /// Length of initial content of the edit buffer. Zero if no initial content exists.
721+ /// Must be less than editBuffer length.
722+ /// </param>
723+ /// <param name="editBuffer">
724+ /// Edit buffer with optional initial content.
725+ /// Caution! Last position in the edit buffer is for a null in native code.
721726 /// </param>
722727 /// <param name="charactersToRead">
723728 /// Number of characters to read from the device.
729+ /// Must be less than editBuffer length.
724730 /// </param>
725731 /// <param name="endOnTab">
726- /// true to allow the user to terminate input by hitting the tab or shift-tab key, in addition to the enter key
732+ /// True to allow the user to terminate input by hitting the tab or shift-tab key, in addition to the enter key
727733 /// </param>
728734 /// <param name="keyState">
729- /// bit mask indicating the state of the control/shift keys at the point input was terminated.
735+ /// Bit mask indicating the state of the control/shift keys at the point input was terminated.
736+ /// </param>
730737 /// </param>
731738 /// <returns></returns>
732739 /// <exception cref="HostException">
733740 /// If Win32's ReadConsole fails
734741 /// </exception>
735742
736- internal static string ReadConsole ( ConsoleHandle consoleHandle , string initialContent ,
737- int charactersToRead , bool endOnTab , out uint keyState )
743+ internal static string ReadConsole (
744+ ConsoleHandle consoleHandle ,
745+ int initialContentLength ,
746+ Span < char > editBuffer ,
747+ int charactersToRead ,
748+ bool endOnTab ,
749+ out uint keyState )
738750 {
739751 Dbg . Assert ( ! consoleHandle . IsInvalid , "ConsoleHandle is not valid" ) ;
740752 Dbg . Assert ( ! consoleHandle . IsClosed , "ConsoleHandle is closed" ) ;
741- Dbg . Assert ( initialContent != null , "if no initial content is desired, pass string.Empty" ) ;
753+ Dbg . Assert ( initialContentLength < editBuffer . Length , "initialContentLength must be less than editBuffer.Length" ) ;
754+ Dbg . Assert ( charactersToRead < editBuffer . Length , "charactersToRead must be less than editBuffer.Length" ) ;
742755 keyState = 0 ;
743756
744757 CONSOLE_READCONSOLE_CONTROL control = new CONSOLE_READCONSOLE_CONTROL ( ) ;
745758
746759 control . nLength = ( ULONG ) Marshal . SizeOf ( control ) ;
747- control . nInitialChars = ( ULONG ) initialContent . Length ;
760+ control . nInitialChars = ( ULONG ) initialContentLength ;
748761 control . dwControlKeyState = 0 ;
749762 if ( endOnTab )
750763 {
@@ -753,28 +766,34 @@ internal static string ReadConsole(ConsoleHandle consoleHandle, string initialCo
753766 control . dwCtrlWakeupMask = ( 1 << TAB ) ;
754767 }
755768
756- DWORD charsReadUnused = 0 ;
757- StringBuilder buffer = new StringBuilder ( initialContent , charactersToRead ) ;
769+ DWORD charsReaded = 0 ;
770+
758771 bool result =
759772 NativeMethods . ReadConsole (
760773 consoleHandle . DangerousGetHandle ( ) ,
761- buffer ,
774+ editBuffer ,
762775 ( DWORD ) charactersToRead ,
763- out charsReadUnused ,
776+ out charsReaded ,
764777 ref control ) ;
765778 keyState = control . dwControlKeyState ;
766779 if ( result == false )
767780 {
768781 int err = Marshal . GetLastWin32Error ( ) ;
769782
770- HostException e = CreateHostException ( err , "ReadConsole" ,
771- ErrorCategory . ReadError , ConsoleControlStrings . ReadConsoleExceptionTemplate ) ;
783+ HostException e = CreateHostException (
784+ err ,
785+ "ReadConsole" ,
786+ ErrorCategory . ReadError ,
787+ ConsoleControlStrings . ReadConsoleExceptionTemplate ) ;
772788 throw e ;
773789 }
774790
775- if ( charsReadUnused > ( uint ) buffer . Length )
776- charsReadUnused = ( uint ) buffer . Length ;
777- return buffer . ToString ( 0 , ( int ) charsReadUnused ) ;
791+ if ( charsReaded > ( uint ) charactersToRead )
792+ {
793+ charsReaded = ( uint ) charactersToRead ;
794+ }
795+
796+ return editBuffer . Slice ( 0 , ( int ) charsReaded ) . ToString ( ) ;
778797 }
779798
780799 /// <summary>
@@ -3019,15 +3038,30 @@ IntPtr reserved
30193038
30203039 [ DllImport ( PinvokeDllNames . ReadConsoleDllName , SetLastError = true , CharSet = CharSet . Unicode ) ]
30213040 [ return : MarshalAs ( UnmanagedType . Bool ) ]
3022- internal static extern bool ReadConsole
3041+ private static extern unsafe bool ReadConsole
30233042 (
30243043 NakedWin32Handle consoleInput ,
3025- StringBuilder buffer ,
3044+ char * lpBuffer ,
30263045 DWORD numberOfCharsToRead ,
30273046 out DWORD numberOfCharsRead ,
30283047 ref CONSOLE_READCONSOLE_CONTROL controlData
30293048 ) ;
30303049
3050+ internal static unsafe bool ReadConsole
3051+ (
3052+ NakedWin32Handle consoleInput ,
3053+ Span < char > buffer ,
3054+ DWORD numberOfCharsToRead ,
3055+ out DWORD numberOfCharsRead ,
3056+ ref CONSOLE_READCONSOLE_CONTROL controlData
3057+ )
3058+ {
3059+ fixed ( char * bufferPtr = & MemoryMarshal . GetReference ( buffer ) )
3060+ {
3061+ return ReadConsole ( consoleInput , bufferPtr , numberOfCharsToRead , out numberOfCharsRead , ref controlData ) ;
3062+ }
3063+ }
3064+
30313065 [ DllImport ( PinvokeDllNames . PeekConsoleInputDllName , SetLastError = true , CharSet = CharSet . Unicode ) ]
30323066 [ return : MarshalAs ( UnmanagedType . Bool ) ]
30333067 internal static extern bool PeekConsoleInput
0 commit comments