/*---{fips-meta:file-header:public}-------------------------------------*\
| o _______ __ _______ _ ______ __ o |
| | ___|__|.-----.| __|| | | |.-----.--| |.-----. |
| | ___| || _ ||__ ||_| | ---|| _ | _ || -__| |
| |___| |__|| __||_______| |______||_____|_____||_____| |
| FipS' CODE |__| > > > > > > > > > > > > > > > > > > > > > > |
| (c) 2004-13 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++ |
| o THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE o |
\*----------------------------------------------------------------------*/
#include "bu_directory_ref.h"
namespace fs { namespace bundle {
Directory_ref::Directory_ref(fo::Bytes_ref dir_blob):
_filelist(nullptr),
_filenames(nullptr)
{
using namespace blob::directory;
FS_ASSERT(!dir_blob.empty());
const Directory *dir = reinterpret_cast<const Directory *>(dir_blob.data());
const Blob &blob = dir->blob;
FS_ASSERT(tag(blob) == Tag('4', 'D', 'I', 'R'));
FS_ASSERT(blob.size == dir_blob.size());
const Block &header_block = dir->header_block;
const Header *header = reinterpret_cast<const Header *>(dir_blob.data() + header_block.offset);
FS_ASSERT(header->version == 1);
const Block &filelist_block = dir->filelist_block;
const Filelist *filelist = reinterpret_cast<const Filelist *>(dir_blob.data() + filelist_block.offset);
const Block &filenames_block = dir->filenames_block;
const Filenames *filenames = reinterpret_cast<const Filenames *>(dir_blob.data() + filenames_block.offset);
_filelist = filelist;
_filenames = filenames;
}
size_t Directory_ref::num_files() const
{
return _filelist->num_files;
}
fo::String_ref Directory_ref::file(Index index) const
{
FS_ASSERT(index.in_range(0, num_files()));
const size_t fname_offset = _filelist->files[index.pos()].fname_offset;
const char *fname = _filenames->data + fname_offset;
return fname;
}
bool Directory_ref::has_file(fo::String_ref fname) const
{
return find_file(fname).valid();
}
Directory_ref::Index Directory_ref::find_file(fo::String_ref fname) const
{
using namespace blob::directory;
// the linear search below, will be later replaced by a binary search,
// using std::lower_bound(), but we need to implement an iterator for
// 'blob::File' first, the sequence is always sorted...
const char *fnames = _filenames->data;
for(size_t i = 0, n = _filelist->num_files; i < n; ++i)
{
const File &cur_file = _filelist->files[i];
const char *cur_fname = fnames + cur_file.fname_offset;
if(strcmp(cur_fname, fname.cstr()) == 0)
return Index::make(i);
}
return Index::invalid();
}
}} // namespace fs::bundle