@@ -138,23 +138,33 @@ static void SetReadOnly(FileInfo fileInfo)
138138
139139 static string [ ] GetLineSplitArray ( string line_value ) => line_value . Split ( ' ' , StringSplitOptions . RemoveEmptyEntries ) ;
140140
141+ internal static bool IsV1Format ( string [ ] line_split_array ) => line_split_array . Length == 3 && line_split_array [ 2 ] == "#Steam++" ;
142+
141143 /// <summary>
142144 /// 处理一行数据
145+ /// <para><see langword="false"/> 当前行格式不正确,不处理直接写入</para>
146+ /// <para><see langword="true"/> 当前行格式正确,开始处理</para>
147+ /// <para><see langword="null"/> 当前行格式不正确,不处理也不写入</para>
143148 /// </summary>
144149 /// <param name="line_num"></param>
145150 /// <param name="domains"></param>
146151 /// <param name="line_value"></param>
147152 /// <param name="line_split_array"></param>
148153 /// <param name="action"></param>
149154 /// <returns></returns>
150- static bool HandleLine ( int line_num , HashSet < string > domains , string line_value , out string [ ] line_split_array , Func < string [ ] , bool > ? func = null )
155+ static bool ? HandleLine ( int line_num , HashSet < string > domains , string line_value , out string [ ] line_split_array , Func < string [ ] , bool ? > ? func = null )
151156 {
152157 line_split_array = GetLineSplitArray ( line_value ) ;
153- var r = func ? . Invoke ( line_split_array ) ?? true ;
154- if ( ! r ) return false ;
158+ if ( func != null )
159+ {
160+ var r = func . Invoke ( line_split_array ) ;
161+ if ( ! r . HasValue ) return null ;
162+ if ( ! r . Value ) return false ;
163+ }
155164 if ( line_split_array . Length < 2 ) return false ;
156165 if ( line_split_array [ 0 ] . StartsWith ( '#' ) ) return false ;
157166 if ( line_split_array . Length > 2 && ! line_split_array [ 2 ] . StartsWith ( '#' ) ) return false ;
167+ if ( IsV1Format ( line_split_array ) ) return null ; // Compat V1
158168 if ( ! domains . Add ( line_split_array [ 1 ] ) )
159169 throw new Exception ( $ "hosts file line { line_num } duplicate") ;
160170 return true ;
@@ -184,6 +194,7 @@ OperationResult HandleHosts(bool isUpdateOrRemove, IReadOnlyDictionary<string, s
184194 {
185195 int line_num = 0 ;
186196 HashSet < string > domains = new ( ) ; // 域名唯一检查
197+ var last_line_value = ( string ? ) null ;
187198 while ( true )
188199 {
189200 line_num ++ ;
@@ -192,36 +203,36 @@ OperationResult HandleHosts(bool isUpdateOrRemove, IReadOnlyDictionary<string, s
192203 if ( line_value == null ) break ;
193204
194205 var not_append = false ;
195- var is_mark = false ;
196206 var is_effective_value = HandleLine ( line_num , domains , line_value , out var line_split_array , line_split_array =>
197207 {
208+ if ( markLength . Contains ( BackupMarkStart ) && ! markLength . Contains ( BackupMarkEnd ) )
209+ {
210+ if ( line_split_array . Length >= 2 && line_split_array [ 0 ] . StartsWith ( '#' ) && int . TryParse ( line_split_array [ 0 ] . TrimStart ( '#' ) , out var bak_line_num ) ) // #{line_num} {line_value}
211+ {
212+ var bak_line_split_array = line_split_array . AsSpan ( ) [ 1 ..] ;
213+ if ( bak_line_split_array . Length >= 2 )
214+ {
215+ backup_datas . TryAdd ( bak_line_split_array [ 1 ] , ( bak_line_num , string . Join ( ' ' , bak_line_split_array . ToArray ( ) ) ) ) ;
216+ }
217+ }
218+ return null ;
219+ }
220+
198221 var mark = GetMarkValue ( line_split_array ) ;
199222 if ( mark == null ) return true ;
200- is_mark = true ;
223+ if ( mark == MarkEnd && ! markLength . Contains ( MarkStart ) ) return null ;
224+ if ( mark == BackupMarkEnd && ! markLength . Contains ( BackupMarkStart ) ) return null ;
225+ if ( ( mark == MarkStart || mark == BackupMarkStart ) && last_line_value != null && string . IsNullOrWhiteSpace ( last_line_value ) )
226+ {
227+ var removeLen = last_line_value . Length + Environment . NewLine . Length ;
228+ stringBuilder . Remove ( stringBuilder . Length - removeLen , removeLen ) ;
229+ }
201230 if ( ! markLength . Add ( mark ) ) throw new Exception ( $ "hosts file mark duplicate, value: { mark } ") ;
202- return false ;
231+ return null ;
203232 } ) ;
204- if ( is_mark ) continue ; // 当前行是 mark 标志,跳过
205- if ( ! is_effective_value ) goto append ; // 当前行是无效值,直接写入
206- if ( line_split_array . Length == 3 && line_split_array [ 2 ] == "#Steam++" ) // Compat V1
207- {
208- domains . Remove ( line_split_array [ 1 ] ) ;
209- continue ;
210- }
233+ if ( ! is_effective_value . HasValue ) goto skip ;
234+ if ( ! is_effective_value . Value ) goto append ; // 当前行是无效值,直接写入
211235 string ip , domain ;
212- if ( markLength . Contains ( BackupMarkStart ) && ! markLength . Contains ( BackupMarkEnd ) )
213- {
214- if ( line_split_array . Length >= 2 && line_split_array [ 0 ] . StartsWith ( '#' ) && int . TryParse ( line_split_array [ 0 ] . TrimStart ( '#' ) , out var bak_line_num ) ) // #{line_num} {line_value}
215- {
216- var bak_line_split_array = line_split_array . AsSpan ( ) [ 1 ..] ;
217- if ( bak_line_split_array . Length >= 2 )
218- {
219- domain = bak_line_split_array [ 1 ] ;
220- backup_datas . TryAdd ( domain , ( bak_line_num , line_value ) ) ;
221- }
222- }
223- continue ;
224- }
225236 ip = line_split_array [ 0 ] ;
226237 domain = line_split_array [ 1 ] ;
227238 var match_domain = has_hosts && hosts . ContainsKey ( domain ) ; // 与要修改的项匹配
@@ -235,11 +246,11 @@ OperationResult HandleHosts(bool isUpdateOrRemove, IReadOnlyDictionary<string, s
235246 }
236247 else // 删除值
237248 {
238- continue ;
249+ goto skip ;
239250 }
240251 }
241252 insert_mark_datas . TryAdd ( domain , ip ) ;
242- continue ;
253+ goto skip ;
243254 }
244255 else // 在标记区域外
245256 {
@@ -250,12 +261,21 @@ OperationResult HandleHosts(bool isUpdateOrRemove, IReadOnlyDictionary<string, s
250261 insert_mark_datas . TryAdd ( domain , ip ) ;
251262 }
252263 backup_insert_mark_datas . TryAdd ( domain , ( line_num , line_value ) ) ;
253- continue ;
264+ goto skip ;
254265 }
255266 }
256267
257- if ( not_append ) continue ;
258- append : stringBuilder . AppendLine ( line_value ) ;
268+ if ( not_append )
269+ {
270+ goto skip ;
271+ }
272+
273+ append : stringBuilder . AppendLine ( line_value ) ;
274+ last_line_value = line_value ;
275+ continue ;
276+
277+ skip : line_num -- ;
278+ continue ;
259279 }
260280 }
261281
@@ -267,11 +287,14 @@ OperationResult HandleHosts(bool isUpdateOrRemove, IReadOnlyDictionary<string, s
267287 }
268288 }
269289
290+ var is_restore = ! has_hosts && ! isUpdateOrRemove ;
291+
270292 void Restore ( IEnumerable < KeyValuePair < string , ( int line_num , string line_value ) > > datas )
271293 {
294+ if ( ! is_restore && datas == backup_datas ) datas = new List < KeyValuePair < string , ( int line_num , string line_value ) > > ( datas ) ;
272295 foreach ( var item in datas )
273296 {
274- var line_index = stringBuilder . GetLineIndex ( item . Value . line_num ) ;
297+ var line_index = stringBuilder . GetLineIndex ( item . Value . line_num - 1 ) ;
275298 var line_value = item . Value . line_value ;
276299 if ( line_index >= 0 )
277300 {
@@ -281,10 +304,10 @@ void Restore(IEnumerable<KeyValuePair<string, (int line_num, string line_value)>
281304 {
282305 stringBuilder . AppendLine ( line_value ) ;
283306 }
307+ if ( ! is_restore ) backup_datas . Remove ( item . Key ) ;
284308 }
285309 }
286310
287- var is_restore = ! has_hosts && ! isUpdateOrRemove ;
288311 if ( is_restore )
289312 {
290313 Restore ( backup_datas ) ;
@@ -308,10 +331,10 @@ void Restore(IEnumerable<KeyValuePair<string, (int line_num, string line_value)>
308331 stringBuilder . AppendLine ( MarkEnd ) ;
309332 }
310333
311- var any_backup_insert_mark_datas = any_insert_mark_datas && backup_insert_mark_datas . Any ( ) ;
312- var insert_backup_datas = any_insert_mark_datas ? backup_datas . Where ( x => insert_mark_datas . ContainsKey ( x . Key ) ) : backup_datas ;
313- if ( any_backup_insert_mark_datas ) insert_backup_datas = insert_backup_datas . Where ( x => ! backup_insert_mark_datas . ContainsKey ( x . Key ) ) ;
314- if ( any_backup_insert_mark_datas || insert_backup_datas . Any ( ) ) // 插入备份数据
334+ var any_backup_insert_mark_datas = backup_insert_mark_datas . Any ( ) ;
335+ var insert_or_remove_backup_datas = any_insert_mark_datas ? backup_datas . Where ( x => insert_mark_datas . ContainsKey ( x . Key ) ) : backup_datas ;
336+ if ( any_backup_insert_mark_datas ) insert_or_remove_backup_datas = insert_or_remove_backup_datas . Where ( x => ! backup_insert_mark_datas . ContainsKey ( x . Key ) ) ;
337+ if ( any_backup_insert_mark_datas || insert_or_remove_backup_datas . Any ( ) ) // 插入备份数据
315338 {
316339 stringBuilder . AppendLine ( ) ;
317340 stringBuilder . AppendLine ( BackupMarkStart ) ;
@@ -325,7 +348,7 @@ void Restore(IEnumerable<KeyValuePair<string, (int line_num, string line_value)>
325348 stringBuilder . AppendLine ( item . Value . line_value ) ;
326349 }
327350 }
328- foreach ( var item in insert_backup_datas )
351+ foreach ( var item in insert_or_remove_backup_datas )
329352 {
330353 stringBuilder . AppendLine ( item . Value . line_value ) ;
331354 }
@@ -368,7 +391,8 @@ void Restore(IEnumerable<KeyValuePair<string, (int line_num, string line_value)>
368391 var line = fileReader . ReadLine ( ) ;
369392 if ( line == null ) break ;
370393 if ( string . IsNullOrWhiteSpace ( line ) ) continue ;
371- if ( ! HandleLine ( index , list , line , out var array ) ) continue ;
394+ var is_effective_value = HandleLine ( index , list , line , out var array ) ;
395+ if ( ! is_effective_value . HasValue || ! is_effective_value . Value ) continue ;
372396 yield return ( array [ 0 ] , array [ 1 ] ) ;
373397 }
374398 }
0 commit comments