22using Source . FileSystem ;
33using Source . VPK ;
44
5+ using System . Runtime . CompilerServices ;
6+ using System . Runtime . InteropServices ;
7+ using System . Text ;
58
69namespace Source . Filesystem ;
710
@@ -40,34 +43,32 @@ public PackStore(string key, string vpkPath) {
4043 Key = key ;
4144 Vpk . Load ( vpkPath ) ;
4245
43- int entryCount = 0 ;
44- foreach ( var dir in Vpk . Directories )
45- entryCount += dir . Entries . Count ;
46-
4746 DirectoryLookups . EnsureCapacity ( Vpk . Directories . Count ) ;
48- EntryLookups . EnsureCapacity ( entryCount ) ;
47+ EntryLookups . EnsureCapacity ( Vpk . EntryCount ) ;
4948
5049 Span < char > buildPath = stackalloc char [ 260 ] ;
51- foreach ( var dir in Vpk . Directories ) {
52- DirectoryLookups [ dir . Path . Hash ( ) ] = dir ;
53-
54- foreach ( var entry in dir . Entries ) {
55- var path = entry . Path . Replace ( '\\ ' , '/' ) ;
56- var filename = entry . Filename ;
57- var ext = entry . Extension ;
58-
59- int strlen = 0 ;
60- if ( path . Length > 0 && path [ 0 ] != ' ' ) {
61- path . CopyTo ( buildPath [ strlen .. ] ) ; strlen += path . Length ;
62- buildPath [ strlen ] = '/' ; strlen += 1 ;
63- }
64- filename . CopyTo ( buildPath [ strlen .. ] ) ; strlen += filename . Length ;
65- buildPath [ strlen ] = '.' ; strlen += 1 ;
66- ext . CopyTo ( buildPath [ strlen .. ] ) ; strlen += ext . Length ;
67-
68- ReadOnlySpan < char > finalSpan = buildPath [ .. strlen ] ;
69- EntryLookups [ finalSpan . Hash ( ) ] = entry ;
50+ foreach ( VpkDirectory dir in Vpk . Directories ) {
51+ int pathLength = Encoding . Latin1 . GetChars ( Vpk . GetPath ( in dir ) , buildPath ) ;
52+ DirectoryLookups [ ( ( ReadOnlySpan < char > ) buildPath [ .. pathLength ] ) . Hash ( ) ] = dir ;
53+ }
54+
55+ foreach ( VpkEntry entry in Vpk . EnumerateEntries ( ) ) {
56+ ReadOnlySpan < byte > path = Vpk . GetPath ( in entry ) ;
57+ ReadOnlySpan < byte > filename = Vpk . GetFilename ( in entry ) ;
58+ ReadOnlySpan < byte > ext = Vpk . GetExtension ( in entry ) ;
59+
60+ int strlen = 0 ;
61+ if ( path . Length > 0 && path [ 0 ] != ' ' ) {
62+ strlen += Encoding . Latin1 . GetChars ( path , buildPath [ strlen .. ] ) ;
63+ buildPath [ .. strlen ] . Replace ( '\\ ' , '/' ) ;
64+ buildPath [ strlen ] = '/' ; strlen += 1 ;
7065 }
66+ strlen += Encoding . Latin1 . GetChars ( filename , buildPath [ strlen .. ] ) ;
67+ buildPath [ strlen ] = '.' ; strlen += 1 ;
68+ strlen += Encoding . Latin1 . GetChars ( ext , buildPath [ strlen .. ] ) ;
69+
70+ ReadOnlySpan < char > finalSpan = buildPath [ .. strlen ] ;
71+ EntryLookups [ finalSpan . Hash ( ) ] = entry ;
7172 }
7273 }
7374 }
@@ -141,8 +142,9 @@ public override bool IsFileWritable(ReadOnlySpan<char> path) {
141142 }
142143
143144 public override IFileHandle ? Open ( ReadOnlySpan < char > path , FileOpenOptions options ) {
144- if ( vpkEntryLookups . TryGetValue ( path . Hash ( ) , out VpkEntry ? entry ) )
145- return new VpkFileHandle ( parent , parent . FindOrAddFileName ( path ) , new MemoryStream ( entry . Data ) ) ;
145+ ref VpkEntry entry = ref CollectionsMarshal . GetValueRefOrNullRef ( vpkEntryLookups , path . Hash ( ) ) ;
146+ if ( ! Unsafe . IsNullRef ( ref entry ) )
147+ return new VpkFileHandle ( parent , parent . FindOrAddFileName ( path ) , new MemoryStream ( store ! . Vpk . ReadData ( in entry ) ) ) ;
146148
147149 return null ;
148150 }
@@ -153,7 +155,8 @@ public override bool IsFileWritable(ReadOnlySpan<char> path) {
153155 public override bool SetFileWritable ( ReadOnlySpan < char > path , bool writable ) => false ;
154156
155157 public override long Size ( ReadOnlySpan < char > path ) {
156- if ( vpkEntryLookups . TryGetValue ( path . Hash ( ) , out VpkEntry ? entry ) )
158+ ref VpkEntry entry = ref CollectionsMarshal . GetValueRefOrNullRef ( vpkEntryLookups , path . Hash ( ) ) ;
159+ if ( ! Unsafe . IsNullRef ( ref entry ) )
157160 return entry . EntryLength ;
158161 return - 1 ;
159162 }
@@ -184,9 +187,14 @@ public override void PrepareFinds(List<string> files, List<string> dirs, string?
184187 int wildcardAsteriskAtFile = wildcardFile . IndexOf ( '*' ) ;
185188 int wildcardAsteriskAtExt = wildcardExt . IndexOf ( '*' ) ;
186189
190+ VpkArchive vpk = store ! . Vpk ;
191+ Span < char > pathBuffer = stackalloc char [ 260 ] ;
192+ Span < char > filenameBuffer = stackalloc char [ 260 ] ;
193+ Span < char > extBuffer = stackalloc char [ 260 ] ;
194+
187195 foreach ( var directory in vpkDirectoryLookups ) {
188196 VpkDirectory dir = directory . Value ;
189- string path = dir . Path ;
197+ ReadOnlySpan < char > path = pathBuffer [ .. Encoding . Latin1 . GetChars ( vpk . GetPath ( in dir ) , pathBuffer ) ] ;
190198 path . FileInfo ( null , out var baseDirectory , out var baseName , out _ ) ;
191199
192200 if ( wildcardAsteriskAtDir == - 1 ) {
@@ -206,35 +214,40 @@ public override void PrepareFinds(List<string> files, List<string> dirs, string?
206214
207215 foreach ( var entryKVP in vpkEntryLookups ) {
208216 VpkEntry entry = entryKVP . Value ;
217+ ReadOnlySpan < char > entryPath = pathBuffer [ .. Encoding . Latin1 . GetChars ( vpk . GetPath ( in entry ) , pathBuffer ) ] ;
209218
210219 if ( wildcardAsteriskAtDir == - 1 ) {
211- if ( ! entry . Path . PathEquals ( wildcardDir ) )
220+ if ( ! entryPath . PathEquals ( wildcardDir ) )
212221 continue ;
213222 }
214223 else {
215- if ( wildcardDir != "*" && ! entry . Path . PathStartsWith ( wildcardDir ) )
224+ if ( wildcardDir != "*" && ! entryPath . PathStartsWith ( wildcardDir ) )
216225 continue ;
217226 }
218227
228+ ReadOnlySpan < char > entryFilename = filenameBuffer [ .. Encoding . Latin1 . GetChars ( vpk . GetFilename ( in entry ) , filenameBuffer ) ] ;
229+
219230 if ( wildcardAsteriskAtFile == - 1 ) {
220- if ( ! entry . Filename . PathEquals ( wildcardFile ) )
231+ if ( ! entryFilename . PathEquals ( wildcardFile ) )
221232 continue ;
222233 }
223234 else {
224- if ( wildcardFile [ 0 ] != '*' && ! entry . Filename . PathStartsWith ( wildcardFile ) )
235+ if ( wildcardFile [ 0 ] != '*' && ! entryFilename . PathStartsWith ( wildcardFile ) )
225236 continue ;
226237 }
227238
239+ ReadOnlySpan < char > entryExt = extBuffer [ .. Encoding . Latin1 . GetChars ( vpk . GetExtension ( in entry ) , extBuffer ) ] ;
240+
228241 if ( wildcardAsteriskAtExt == - 1 ) {
229- if ( ! entry . Extension . PathEquals ( wildcardExt ) )
242+ if ( ! entryExt . PathEquals ( wildcardExt ) )
230243 continue ;
231244 }
232245 else {
233- if ( ! wildcardExt . IsEmpty && wildcardExt [ 0 ] != '*' && ! entry . Extension . PathStartsWith ( wildcardExt ) )
246+ if ( ! wildcardExt . IsEmpty && wildcardExt [ 0 ] != '*' && ! entryExt . PathStartsWith ( wildcardExt ) )
234247 continue ;
235248 }
236249
237- files . Add ( entry . FilenameAndExtension ) ;
250+ files . Add ( string . Concat ( entryFilename , "." , entryExt ) ) ;
238251 }
239252 }
240253}
0 commit comments