@@ -71,25 +71,10 @@ public FileIO(CodeContext/*!*/ context, int fd, string mode = "r", bool closefd
7171 throw PythonOps . ValueError ( "fd must be >= 0" ) ;
7272 }
7373
74- PythonContext pc = context . LanguageContext ;
75-
76- _context = pc ;
77- switch ( StandardizeMode ( mode ) ) {
78- case "r" : this . mode = "rb" ; break ;
79- case "w" : this . mode = "wb" ; break ;
80- case "a" : this . mode = "w" ; break ;
81- case "r+" :
82- case "+r" : this . mode = "rb+" ; break ;
83- case "w+" :
84- case "+w" : this . mode = "rb+" ; break ;
85- case "a+" :
86- case "+a" : this . mode = "r+" ; break ;
87- default :
88- BadMode ( mode ) ;
89- break ;
90- }
74+ _context = context . LanguageContext ;
75+ this . mode = NormalizeMode ( mode , out _ ) ;
9176
92- object fileObject = pc . FileManager . GetObjectFromId ( fd ) ; // OSError here if no such fd
77+ object fileObject = _context . FileManager . GetObjectFromId ( fd ) ; // OSError here if no such fd
9378
9479 // FileManager interface guarantees fileObject is
9580 // one of these two types
@@ -117,55 +102,38 @@ public FileIO(CodeContext/*!*/ context, string name, string mode = "r", bool clo
117102 this . name = name ;
118103 PlatformAdaptationLayer pal = context . LanguageContext . DomainManager . Platform ;
119104
120- int flags = 0 ;
121- switch ( StandardizeMode ( mode ) ) {
122- case "r" :
123- _readStream = _writeStream = OpenFile ( context , pal , name , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) ;
124- this . mode = "rb" ;
125- flags |= O_RDONLY ;
126- break ;
127- case "w" :
128- _readStream = _writeStream = OpenFile ( context , pal , name , FileMode . Create , FileAccess . Write , FileShare . ReadWrite ) ;
129- this . mode = "wb" ;
130- flags |= O_CREAT | O_TRUNC | O_WRONLY ;
131- break ;
132- case "a" :
133- _readStream = _writeStream = OpenFile ( context , pal , name , FileMode . Append , FileAccess . Write , FileShare . ReadWrite ) ;
134- _readStream . Seek ( 0L , SeekOrigin . End ) ;
135- this . mode = "ab" ;
136- flags |= O_APPEND | O_CREAT ;
137- break ;
138- case "r+" :
139- case "+r" :
140- _readStream = _writeStream = OpenFile ( context , pal , name , FileMode . Open , FileAccess . ReadWrite , FileShare . ReadWrite ) ;
141- this . mode = "rb+" ;
142- flags |= O_RDWR ;
143- break ;
144- case "w+" :
145- case "+w" :
146- _readStream = _writeStream = OpenFile ( context , pal , name , FileMode . Create , FileAccess . ReadWrite , FileShare . ReadWrite ) ;
147- this . mode = "rb+" ;
148- flags |= O_CREAT | O_TRUNC | O_RDWR ;
149- break ;
150- case "a+" :
151- case "+a" :
152- _readStream = OpenFile ( context , pal , name , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) ;
153- _writeStream = OpenFile ( context , pal , name , FileMode . Append , FileAccess . Write , FileShare . ReadWrite ) ;
154- _readStream . Seek ( 0L , SeekOrigin . End ) ;
155- _writeStream . Seek ( 0L , SeekOrigin . End ) ;
156- this . mode = "ab+" ;
157- flags |= O_APPEND | O_CREAT | O_RDWR ;
158- break ;
159- default :
160- BadMode ( mode ) ;
161- break ;
162- }
163-
164- _closefd = true ;
165-
166105 _context = context . LanguageContext ;
167-
168- if ( opener != null ) {
106+ this . mode = NormalizeMode ( mode , out int flags ) ;
107+
108+ if ( opener is null ) {
109+ switch ( this . mode ) {
110+ case "rb" :
111+ _readStream = _writeStream = OpenFile ( context , pal , name , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) ;
112+ break ;
113+ case "wb" :
114+ _readStream = _writeStream = OpenFile ( context , pal , name , FileMode . Create , FileAccess . Write , FileShare . ReadWrite ) ;
115+ break ;
116+ case "ab" :
117+ _readStream = _writeStream = OpenFile ( context , pal , name , FileMode . Append , FileAccess . Write , FileShare . ReadWrite ) ;
118+ _readStream . Seek ( 0L , SeekOrigin . End ) ;
119+ break ;
120+ case "rb+" :
121+ _readStream = _writeStream = OpenFile ( context , pal , name , FileMode . Open , FileAccess . ReadWrite , FileShare . ReadWrite ) ;
122+ break ;
123+ case "wb+" :
124+ _readStream = _writeStream = OpenFile ( context , pal , name , FileMode . Create , FileAccess . ReadWrite , FileShare . ReadWrite ) ;
125+ break ;
126+ case "ab+" :
127+ _readStream = OpenFile ( context , pal , name , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) ;
128+ _writeStream = OpenFile ( context , pal , name , FileMode . Append , FileAccess . Write , FileShare . ReadWrite ) ;
129+ _readStream . Seek ( 0L , SeekOrigin . End ) ;
130+ _writeStream . Seek ( 0L , SeekOrigin . End ) ;
131+ break ;
132+ default :
133+ throw new InvalidOperationException ( ) ;
134+ }
135+ }
136+ else {
169137 object fdobj = PythonOps . CallWithContext ( context , opener , name , flags ) ;
170138 if ( fdobj is int fd ) {
171139 if ( fd < 0 ) {
@@ -183,58 +151,86 @@ public FileIO(CodeContext/*!*/ context, string name, string mode = "r", bool clo
183151 throw PythonOps . TypeError ( "expected integer from opener" ) ;
184152 }
185153 }
154+
155+ _closefd = true ;
186156 }
187157
188- /// <summary>
189- /// Remove all 'b's from mode string to simplify parsing
190- /// </summary>
191- private static string StandardizeMode ( string mode ) {
192- int index = mode . IndexOf ( 'b' ) ;
158+ private static string NormalizeMode ( string mode , out int flags ) {
159+ switch ( StandardizeMode ( mode ) ) {
160+ case "r" :
161+ flags = O_RDONLY ;
162+ return "rb" ;
163+ case "w" :
164+ flags = O_CREAT | O_TRUNC | O_WRONLY ;
165+ return "wb" ;
166+ case "a" :
167+ flags = O_APPEND | O_CREAT ;
168+ return "ab" ;
169+ case "r+" :
170+ case "+r" :
171+ flags = O_RDWR ;
172+ return "rb+" ;
173+ case "w+" :
174+ case "+w" :
175+ flags = O_CREAT | O_TRUNC | O_RDWR ;
176+ return "wb+" ;
177+ case "a+" :
178+ case "+a" :
179+ flags = O_APPEND | O_CREAT | O_RDWR ;
180+ return "ab+" ;
181+ default :
182+ throw BadMode ( mode ) ;
183+ }
193184
194- if ( index == mode . Length - 1 ) {
195- mode = mode . Substring ( 0 , index ) ;
196- } else if ( index >= 0 ) {
197- StringBuilder sb = new StringBuilder ( mode . Substring ( 0 , index ) , mode . Length - 1 ) ;
198- for ( int pos = index + 1 ; pos < mode . Length ; pos ++ ) {
199- if ( mode [ pos ] != 'b' ) {
200- sb . Append ( mode [ pos ] ) ;
185+ // remove all 'b's from mode string to simplify parsing
186+ static string StandardizeMode ( string mode ) {
187+ int index = mode . IndexOf ( 'b' ) ;
188+
189+ if ( index == mode . Length - 1 ) {
190+ mode = mode . Substring ( 0 , index ) ;
191+ } else if ( index >= 0 ) {
192+ StringBuilder sb = new StringBuilder ( mode . Substring ( 0 , index ) , mode . Length - 1 ) ;
193+ for ( int pos = index + 1 ; pos < mode . Length ; pos ++ ) {
194+ if ( mode [ pos ] != 'b' ) {
195+ sb . Append ( mode [ pos ] ) ;
196+ }
201197 }
198+ mode = sb . ToString ( ) ;
202199 }
203- mode = sb . ToString ( ) ;
204- }
205200
206- return mode ;
207- }
201+ return mode ;
202+ }
208203
209- private static void BadMode ( string mode ) {
210- bool foundMode = false , foundPlus = false ;
211- foreach ( char c in mode ) {
212- switch ( c ) {
213- case 'r' :
214- case 'w' :
215- case 'a' :
216- if ( foundMode ) {
217- throw PythonOps . ValueError ( "Must have exactly one of read/write/append mode" ) ;
218- } else {
219- foundMode = true ;
204+ static Exception BadMode ( string mode ) {
205+ bool foundMode = false , foundPlus = false ;
206+ foreach ( char c in mode ) {
207+ switch ( c ) {
208+ case 'r' :
209+ case 'w' :
210+ case 'a' :
211+ if ( foundMode ) {
212+ return PythonOps . ValueError ( "Must have exactly one of read/write/append mode" ) ;
213+ } else {
214+ foundMode = true ;
215+ continue ;
216+ }
217+ case '+' :
218+ if ( foundPlus ) {
219+ return PythonOps . ValueError ( "Must have exactly one of read/write/append mode" ) ;
220+ } else {
221+ foundPlus = true ;
222+ continue ;
223+ }
224+ case 'b' :
225+ // any number of 'b's is acceptable
220226 continue ;
221- }
222- case '+' :
223- if ( foundPlus ) {
224- throw PythonOps . ValueError ( "Must have exactly one of read/write/append mode" ) ;
225- } else {
226- foundPlus = true ;
227- continue ;
228- }
229- case 'b' :
230- // any number of 'b's is acceptable
231- continue ;
232- default :
233- throw PythonOps . ValueError ( "invalid mode: {0}" , mode ) ;
227+ default :
228+ return PythonOps . ValueError ( "invalid mode: {0}" , mode ) ;
229+ }
234230 }
235- }
236231
237- throw PythonOps . ValueError ( "Must have exactly one of read/write/append mode" ) ;
232+ return PythonOps . ValueError ( "Must have exactly one of read/write/append mode" ) ;
233+ }
238234 }
239235
240236 #endregion
0 commit comments