11using System ;
22using System . IO ;
3+ using SabreTools . Models . MicrosoftCabinet ;
34
45namespace SabreTools . Serialization . Wrappers
56{
6- public partial class MicrosoftCabinet : WrapperBase < Models . MicrosoftCabinet . Cabinet >
7+ public partial class MicrosoftCabinet : WrapperBase < Cabinet >
78 {
89 #region Descriptive Properties
910
@@ -14,20 +15,20 @@ public partial class MicrosoftCabinet : WrapperBase<Models.MicrosoftCabinet.Cabi
1415
1516 #region Extension Properties
1617
17- /// <inheritdoc cref="Models.MicrosoftCabinet. Cabinet.Files"/>
18- public Models . MicrosoftCabinet . CFFILE [ ] ? Files => Model . Files ;
18+ /// <inheritdoc cref="Cabinet.Files"/>
19+ public CFFILE [ ] ? Files => Model . Files ;
1920
20- /// <inheritdoc cref="Models.MicrosoftCabinet. CFHEADER.FileCount"/>
21+ /// <inheritdoc cref="CFHEADER.FileCount"/>
2122 public int FileCount => Model . Header ? . FileCount ?? 0 ;
2223
23- /// <inheritdoc cref="Models.MicrosoftCabinet. Cabinet.Folders"/>
24- public Models . MicrosoftCabinet . CFFOLDER [ ] ? Folders => Model . Folders ;
24+ /// <inheritdoc cref="Cabinet.Folders"/>
25+ public CFFOLDER [ ] ? Folders => Model . Folders ;
2526
26- /// <inheritdoc cref="Models.MicrosoftCabinet. CFHEADER.FolderCount"/>
27+ /// <inheritdoc cref="CFHEADER.FolderCount"/>
2728 public int FolderCount => Model . Header ? . FolderCount ?? 0 ;
2829
29- /// <inheritdoc cref="Models.MicrosoftCabinet. Cabinet.Header"/>
30- public Models . MicrosoftCabinet . CFHEADER ? Header => Model . Header ;
30+ /// <inheritdoc cref="Cabinet.Header"/>
31+ public CFHEADER ? Header => Model . Header ;
3132
3233 /// <summary>
3334 /// Reference to the next cabinet header
@@ -46,14 +47,14 @@ public partial class MicrosoftCabinet : WrapperBase<Models.MicrosoftCabinet.Cabi
4647 #region Constructors
4748
4849 /// <inheritdoc/>
49- public MicrosoftCabinet ( Models . MicrosoftCabinet . Cabinet ? model , byte [ ] ? data , int offset )
50+ public MicrosoftCabinet ( Cabinet ? model , byte [ ] ? data , int offset )
5051 : base ( model , data , offset )
5152 {
5253 // All logic is handled by the base class
5354 }
5455
5556 /// <inheritdoc/>
56- public MicrosoftCabinet ( Models . MicrosoftCabinet . Cabinet ? model , Stream ? data )
57+ public MicrosoftCabinet ( Cabinet ? model , Stream ? data )
5758 : base ( model , data )
5859 {
5960 // All logic is handled by the base class
@@ -298,6 +299,87 @@ private static uint S(byte[] a, int b, int x)
298299 }
299300 }
300301
302+ /// <summary>
303+ /// Get the corrected folder index
304+ /// </summary>
305+ public int GetFolderIndex ( CFFILE file )
306+ {
307+ return file . FolderIndex switch
308+ {
309+ FolderIndex . CONTINUED_FROM_PREV => 0 ,
310+ FolderIndex . CONTINUED_TO_NEXT => ( Header ? . FolderCount ?? 1 ) - 1 ,
311+ FolderIndex . CONTINUED_PREV_AND_NEXT => 0 ,
312+ _ => ( int ) file . FolderIndex ,
313+ } ;
314+ }
315+
316+ #endregion
317+
318+ #region Folders
319+
320+ /// <summary>
321+ /// Get the set of data blocks for a folder
322+ /// </summary>
323+ public CFDATA [ ] ? GetDataBlocks ( string file , CFFOLDER ? folder , int folderIndex , bool skipPrev = false , bool skipNext = false )
324+ {
325+ // Skip invalid folders
326+ if ( folder ? . DataBlocks == null || folder . DataBlocks . Length == 0 )
327+ return null ;
328+
329+ // Get all files for the folder
330+ var files = GetFiles ( folderIndex ) ;
331+ if ( files . Length == 0 )
332+ return folder . DataBlocks ;
333+
334+ // Check if the folder spans backward
335+ CFDATA [ ] prevBlocks = [ ] ;
336+ if ( ! skipPrev && Array . Exists ( files , f => f . FolderIndex == FolderIndex . CONTINUED_FROM_PREV || f . FolderIndex == FolderIndex . CONTINUED_PREV_AND_NEXT ) )
337+ {
338+ var prev = OpenPrevious ( file ) ;
339+ if ( prev ? . Model ? . Header != null && prev . Model . Folders != null )
340+ {
341+ int prevFolderIndex = prev . Model . Header . FolderCount ;
342+ var prevFolder = prev . Model . Folders [ prevFolderIndex - 1 ] ;
343+ prevBlocks = prev . GetDataBlocks ( file , prevFolder , prevFolderIndex , skipNext : true ) ?? [ ] ;
344+ }
345+ }
346+
347+ // Check if the folder spans forward
348+ CFDATA [ ] nextBlocks = [ ] ;
349+ if ( ! skipNext && Array . Exists ( files , f => f . FolderIndex == FolderIndex . CONTINUED_TO_NEXT || f . FolderIndex == FolderIndex . CONTINUED_PREV_AND_NEXT ) )
350+ {
351+ var next = OpenNext ( file ) ;
352+ if ( next ? . Model ? . Header != null && next . Model . Folders != null )
353+ {
354+ var nextFolder = next . Model . Folders [ 0 ] ;
355+ nextBlocks = next . GetDataBlocks ( file , nextFolder , 0 , skipPrev : true ) ?? [ ] ;
356+ }
357+ }
358+
359+ // Return all found blocks in order
360+ return [ .. prevBlocks , .. folder . DataBlocks , .. nextBlocks ] ;
361+ }
362+
363+ /// <summary>
364+ /// Get all files for the current folder index
365+ /// </summary>
366+ public CFFILE [ ] GetFiles ( int folderIndex )
367+ {
368+ // Ignore invalid archives
369+ if ( Files == null )
370+ return [ ] ;
371+
372+ // Get all files with a name and matching index
373+ return Array . FindAll ( Files , f =>
374+ {
375+ if ( string . IsNullOrEmpty ( f . Name ) )
376+ return false ;
377+
378+ int fileFolder = GetFolderIndex ( f ) ;
379+ return fileFolder == folderIndex ;
380+ } ) ;
381+ }
382+
301383 #endregion
302384 }
303385}
0 commit comments