Skip to content

Commit f6f61ac

Browse files
committed
Refactor file pointer management with RAII VarkFP wrapper
1 parent 41f638b commit f6f61ac

1 file changed

Lines changed: 89 additions & 101 deletions

File tree

vark.h

Lines changed: 89 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,32 @@ struct VarkShardInfo
105105
const uint8_t* pCompressedData; // pointer to start of compressed chunks (mmap only, nullptr for FP)
106106
};
107107

108+
// Simple RAII for conditional FILE* ownership
109+
struct VarkFP {
110+
FILE* fp = nullptr;
111+
bool owns = false;
112+
VarkFP() = default;
113+
VarkFP( FILE* f, bool own ) : fp(f), owns(own) {}
114+
~VarkFP() { if ( owns && fp ) fclose( fp ); }
115+
operator FILE*() const { return fp; }
116+
explicit operator bool() const { return fp != nullptr; }
117+
};
118+
119+
// Acquires read FP from vark. Returns empty handle if MMAP mode.
120+
static VarkFP VarkAcquireReadFP( Vark& vark )
121+
{
122+
if ( (vark.flags & VARK_MMAP) && vark.mmapHandle ) return {};
123+
if ( (vark.flags & VARK_PERSISTENT_FP) && vark.fp ) return { vark.fp, false };
124+
return { fopen( vark.path.string().c_str(), "rb" ), true };
125+
}
126+
127+
// Acquires read/write FP from vark for append operations.
128+
static VarkFP VarkAcquireWriteFP( Vark& vark )
129+
{
130+
if ( (vark.flags & VARK_PERSISTENT_FP) && vark.fp ) return { vark.fp, false };
131+
return { fopen( vark.path.string().c_str(), "r+b" ), true };
132+
}
133+
108134
// For MMAP: parses VSHF from memory, returns header. pOffsets points into mmap via tempShardBuffer copy.
109135
static bool VarkParseVSHF_MMAP( Vark& vark, const uint8_t* ptr, size_t entrySize, VarkShardInfo& out )
110136
{
@@ -361,11 +387,8 @@ void VarkCloseArchive( Vark& vark )
361387
bool VarkDecompressFile( Vark& vark, const std::string& file, std::vector< uint8_t >& data )
362388
{
363389
const VarkFile* entry = nullptr;
364-
FILE* fp = nullptr;
365-
std::vector< uint8_t >* pCompressedData = nullptr;
366390
uint64_t uncompressedSize = 0;
367391
uint64_t compressedSize = 0;
368-
bool ownFP = false;
369392

370393
if ( vark.flags & VARK_WRITE ) return false;
371394

@@ -375,37 +398,36 @@ bool VarkDecompressFile( Vark& vark, const std::string& file, std::vector< uint8
375398

376399
if ( entry->shardSize > 0 )
377400
{
378-
if ( (vark.flags & VARK_MMAP) && vark.mmapHandle )
401+
VarkFP fp = VarkAcquireReadFP( vark );
402+
mio::mmap_source* mmap = (vark.flags & VARK_MMAP) ? (mio::mmap_source*)vark.mmapHandle : nullptr;
403+
404+
VarkShardInfo hdr;
405+
uint64_t dataStartPos = 0;
406+
407+
if ( mmap )
379408
{
380-
mio::mmap_source* mmap = (mio::mmap_source*)vark.mmapHandle;
381409
if ( !mmap->is_open() ) return false;
382-
383-
VarkShardInfo hdr;
384410
if ( !VarkParseVSHF_MMAP( vark, (const uint8_t*)mmap->data() + entry->offset, (size_t)entry->size, hdr ) ) return false;
385-
return VarkDecompressShards( vark, nullptr, hdr, entry->shardSize, 0, 0, hdr.totalUncompressedSize, data );
386411
}
387412
else
388413
{
389-
if ( (vark.flags & VARK_PERSISTENT_FP) && vark.fp ) fp = vark.fp;
390-
else { fp = fopen( vark.path.string().c_str(), "rb" ); if ( !fp ) return false; ownFP = true; }
391-
392-
if ( VARK_FSEEK( fp, (long long)entry->offset, SEEK_SET ) != 0 ) goto error1;
393-
394-
VarkShardInfo hdr;
395-
if ( !VarkParseVSHF_Fp( vark, fp, hdr ) ) goto error1;
396-
if ( !VarkDecompressShards( vark, fp, hdr, entry->shardSize, VARK_FTELL( fp ), 0, hdr.totalUncompressedSize, data ) ) goto error1;
397-
398-
if ( ownFP ) fclose( fp );
399-
return true;
414+
if ( !fp ) return false;
415+
if ( VARK_FSEEK( fp, (long long)entry->offset, SEEK_SET ) != 0 ) return false;
416+
if ( !VarkParseVSHF_Fp( vark, fp, hdr ) ) return false;
417+
dataStartPos = VARK_FTELL( fp );
400418
}
419+
420+
return VarkDecompressShards( vark, fp, hdr, entry->shardSize, dataStartPos, 0, hdr.totalUncompressedSize, data );
401421
}
402422

403423
if ( entry->size < 8 ) return false;
404424
compressedSize = entry->size - 8;
405425

406-
if ( (vark.flags & VARK_MMAP) && vark.mmapHandle )
426+
VarkFP fp = VarkAcquireReadFP( vark );
427+
mio::mmap_source* mmap = (vark.flags & VARK_MMAP) ? (mio::mmap_source*)vark.mmapHandle : nullptr;
428+
429+
if ( mmap )
407430
{
408-
mio::mmap_source* mmap = (mio::mmap_source*)vark.mmapHandle;
409431
if ( !mmap->is_open() ) return false;
410432
if ( entry->offset + 8 + compressedSize > mmap->size() ) return false;
411433

@@ -421,36 +443,24 @@ bool VarkDecompressFile( Vark& vark, const std::string& file, std::vector< uint8
421443
return true;
422444
}
423445

424-
if ( (vark.flags & VARK_PERSISTENT_FP) && vark.fp ) fp = vark.fp;
425-
else { fp = fopen( vark.path.string().c_str(), "rb" ); if ( !fp ) goto error0; ownFP = true; }
426-
427-
if ( VARK_FSEEK( fp, (long long)entry->offset, SEEK_SET ) != 0 ) goto error1;
428-
if ( fread( &uncompressedSize, sizeof(uncompressedSize), 1, fp ) != 1 ) goto error1;
446+
if ( !fp ) return false;
447+
if ( VARK_FSEEK( fp, (long long)entry->offset, SEEK_SET ) != 0 ) return false;
448+
if ( fread( &uncompressedSize, sizeof(uncompressedSize), 1, fp ) != 1 ) return false;
429449

430-
compressedSize = entry->size - 8;
431-
pCompressedData = &vark.tempBuffer;
432-
pCompressedData->resize( (size_t)compressedSize );
433-
450+
vark.tempBuffer.resize( (size_t)compressedSize );
434451
if ( compressedSize > 0 )
435452
{
436-
if ( fread( pCompressedData->data(), 1, (size_t)compressedSize, fp ) != compressedSize ) goto error1;
453+
if ( fread( vark.tempBuffer.data(), 1, (size_t)compressedSize, fp ) != compressedSize ) return false;
437454
}
438455

439-
if ( ownFP ) fclose( fp );
440-
441456
data.resize( (size_t)uncompressedSize );
442457
if ( uncompressedSize > 0 )
443458
{
444-
int res = lzav::lzav_decompress( pCompressedData->data(), data.data(), (int)compressedSize, (int)uncompressedSize );
459+
int res = lzav::lzav_decompress( vark.tempBuffer.data(), data.data(), (int)compressedSize, (int)uncompressedSize );
445460
if ( res < 0 || (uint64_t)res != uncompressedSize ) return false;
446461
}
447462

448463
return true;
449-
450-
error1:
451-
if ( ownFP && fp ) fclose( fp );
452-
error0:
453-
return false;
454464
}
455465

456466
bool VarkDecompressFileSharded( Vark& vark, const std::string& file, uint64_t offset, uint64_t size, std::vector< uint8_t >& data )
@@ -464,48 +474,32 @@ bool VarkDecompressFileSharded( Vark& vark, const std::string& file, uint64_t of
464474

465475
if ( entry->shardSize == 0 ) return false;
466476

467-
FILE* fp = nullptr;
468-
bool ownFP = false;
477+
VarkFP fp = VarkAcquireReadFP( vark );
478+
mio::mmap_source* mmap = (vark.flags & VARK_MMAP) ? (mio::mmap_source*)vark.mmapHandle : nullptr;
469479

470-
if ( ( vark.flags & VARK_MMAP ) && vark.mmapHandle )
480+
VarkShardInfo hdr;
481+
uint64_t dataStartPos = 0;
482+
483+
if ( mmap )
471484
{
472-
mio::mmap_source* mmap = ( mio::mmap_source* ) vark.mmapHandle;
473485
if ( !mmap->is_open() ) return false;
474-
475-
VarkShardInfo hdr;
476-
if ( !VarkParseVSHF_MMAP( vark, ( const uint8_t* ) mmap->data() + entry->offset, (size_t)entry->size, hdr ) ) return false;
477-
if ( offset + size > hdr.totalUncompressedSize ) return false;
478-
479-
return VarkDecompressShards( vark, nullptr, hdr, entry->shardSize, 0, offset, size, data );
486+
if ( !VarkParseVSHF_MMAP( vark, (const uint8_t*)mmap->data() + entry->offset, (size_t)entry->size, hdr ) ) return false;
480487
}
481488
else
482489
{
483-
if ( ( vark.flags & VARK_PERSISTENT_FP ) && vark.fp ) fp = vark.fp;
484-
else { fp = fopen( vark.path.string().c_str(), "rb" ); if ( !fp ) return false; ownFP = true; }
485-
486-
if ( VARK_FSEEK( fp, ( long long ) entry->offset, SEEK_SET ) != 0 ) goto error1;
487-
488-
VarkShardInfo hdr;
489-
if ( !VarkParseVSHF_Fp( vark, fp, hdr ) ) goto error1;
490-
if ( offset + size > hdr.totalUncompressedSize ) goto error1;
491-
492-
uint64_t dataStartPos = VARK_FTELL( fp );
493-
if ( !VarkDecompressShards( vark, fp, hdr, entry->shardSize, dataStartPos, offset, size, data ) ) goto error1;
494-
495-
if ( ownFP ) fclose( fp );
496-
return true;
490+
if ( !fp ) return false;
491+
if ( VARK_FSEEK( fp, (long long)entry->offset, SEEK_SET ) != 0 ) return false;
492+
if ( !VarkParseVSHF_Fp( vark, fp, hdr ) ) return false;
493+
dataStartPos = VARK_FTELL( fp );
497494
}
498495

499-
error1:
500-
if ( ownFP && fp ) fclose( fp );
501-
return false;
496+
if ( offset + size > hdr.totalUncompressedSize ) return false;
497+
498+
return VarkDecompressShards( vark, fp, hdr, entry->shardSize, dataStartPos, offset, size, data );
502499
}
503500

504501
bool VarkCompressAppendFile( Vark& vark, const std::string& file, uint32_t flags )
505502
{
506-
FILE* srcFp = nullptr;
507-
FILE* fp = nullptr;
508-
std::vector< uint8_t > srcData;
509503
VarkFile newFile;
510504
long long srcLen = 0;
511505
uint64_t tableOffset = 0;
@@ -515,26 +509,29 @@ bool VarkCompressAppendFile( Vark& vark, const std::string& file, uint32_t flags
515509

516510
if ( !( vark.flags & VARK_WRITE ) ) return false;
517511

518-
srcFp = fopen( file.c_str(), "rb" );
519-
if ( !srcFp ) goto error0;
520-
521-
VARK_FSEEK( srcFp, 0, SEEK_END );
522-
srcLen = VARK_FTELL( srcFp );
523-
VARK_FSEEK( srcFp, 0, SEEK_SET );
524-
525-
srcData.resize( (size_t)srcLen );
526-
if ( srcLen > 0 )
512+
// Read source file
513+
std::vector< uint8_t > srcData;
527514
{
528-
if ( fread( srcData.data(), 1, (size_t)srcLen, srcFp ) != (size_t)srcLen ) goto error1;
529-
}
530-
fclose( srcFp );
515+
VarkFP srcFp( fopen( file.c_str(), "rb" ), true );
516+
if ( !srcFp ) return false;
517+
518+
VARK_FSEEK( srcFp, 0, SEEK_END );
519+
srcLen = VARK_FTELL( srcFp );
520+
VARK_FSEEK( srcFp, 0, SEEK_SET );
531521

532-
if ( (vark.flags & VARK_PERSISTENT_FP) && vark.fp ) fp = vark.fp;
533-
else { fp = fopen( vark.path.string().c_str(), "r+b" ); if ( !fp ) goto error0; }
522+
srcData.resize( (size_t)srcLen );
523+
if ( srcLen > 0 )
524+
{
525+
if ( fread( srcData.data(), 1, (size_t)srcLen, srcFp ) != (size_t)srcLen ) return false;
526+
}
527+
} // srcFp closes automatically here
528+
529+
VarkFP fp = VarkAcquireWriteFP( vark );
530+
if ( !fp ) return false;
534531

535-
if ( VARK_FSEEK( fp, 4, SEEK_SET ) != 0 ) goto error2;
536-
if ( fread( &tableOffset, sizeof(tableOffset), 1, fp ) != 1 ) goto error2;
537-
if ( VARK_FSEEK( fp, (long long)tableOffset, SEEK_SET ) != 0 ) goto error2;
532+
if ( VARK_FSEEK( fp, 4, SEEK_SET ) != 0 ) return false;
533+
if ( fread( &tableOffset, sizeof(tableOffset), 1, fp ) != 1 ) return false;
534+
if ( VARK_FSEEK( fp, (long long)tableOffset, SEEK_SET ) != 0 ) return false;
538535

539536
newFile.offset = tableOffset;
540537
newFile.path = file;
@@ -583,13 +580,13 @@ bool VarkCompressAppendFile( Vark& vark, const std::string& file, uint32_t flags
583580
int bound = lzav::lzav_compress_bound( (int)srcLen );
584581
std::vector< uint8_t > dstData( bound );
585582
int compressedLen = lzav::lzav_compress_default( srcData.data(), dstData.data(), (int)srcLen, bound );
586-
if ( compressedLen == 0 && srcLen > 0 ) goto error2;
583+
if ( compressedLen == 0 && srcLen > 0 ) return false;
587584

588585
uncompressedSize = (uint64_t)srcLen;
589-
if ( fwrite( &uncompressedSize, sizeof(uncompressedSize), 1, fp ) != 1 ) goto error2;
586+
if ( fwrite( &uncompressedSize, sizeof(uncompressedSize), 1, fp ) != 1 ) return false;
590587
if ( compressedLen > 0 )
591588
{
592-
if ( fwrite( dstData.data(), 1, compressedLen, fp ) != (size_t)compressedLen ) goto error2;
589+
if ( fwrite( dstData.data(), 1, compressedLen, fp ) != (size_t)compressedLen ) return false;
593590
}
594591
newFile.size = 8 + compressedLen;
595592
}
@@ -599,7 +596,7 @@ bool VarkCompressAppendFile( Vark& vark, const std::string& file, uint32_t flags
599596

600597
newTableOffset = (uint64_t)VARK_FTELL( fp );
601598
count = vark.files.size();
602-
if ( fwrite( &count, sizeof(count), 1, fp ) != 1 ) goto error2;
599+
if ( fwrite( &count, sizeof(count), 1, fp ) != 1 ) return false;
603600

604601
for ( const auto& f : vark.files )
605602
{
@@ -614,22 +611,13 @@ bool VarkCompressAppendFile( Vark& vark, const std::string& file, uint32_t flags
614611
fwrite( &count, sizeof(count), 1, fp );
615612
for ( const auto& f : vark.files ) fwrite( &f.shardSize, sizeof(uint32_t), 1, fp );
616613

617-
if ( VARK_FSEEK( fp, 4, SEEK_SET ) != 0 ) goto error2;
618-
if ( fwrite( &newTableOffset, sizeof(newTableOffset), 1, fp ) != 1 ) goto error2;
614+
if ( VARK_FSEEK( fp, 4, SEEK_SET ) != 0 ) return false;
615+
if ( fwrite( &newTableOffset, sizeof(newTableOffset), 1, fp ) != 1 ) return false;
619616

620617
VARK_FSEEK( fp, 0, SEEK_END );
621618
vark.size = (uint64_t)VARK_FTELL( fp );
622619

623-
if ( fp != vark.fp ) fclose( fp );
624620
return true;
625-
626-
error2:
627-
if ( fp != vark.fp ) fclose( fp );
628-
return false;
629-
error1:
630-
fclose( srcFp );
631-
error0:
632-
return false;
633621
}
634622

635623
#endif // VARK_IMPLEMENTATION

0 commit comments

Comments
 (0)