50 unsigned dirent_start;
56 unsigned long bb_blocks[109];
60 void load(
const unsigned char* buffer );
61 void save(
unsigned char* buffer );
68 static const unsigned Eof;
69 static const unsigned Avail;
70 static const unsigned Bat;
71 static const unsigned MetaBat;
75 unsigned long count();
76 void resize(
unsigned long newsize );
77 void preserve(
unsigned long n );
78 void set(
unsigned long index,
unsigned long val );
80 void setChain( std::vector<unsigned long> );
81 std::vector<unsigned long> follow(
unsigned long start );
82 unsigned long operator[](
unsigned long index );
83 void load(
const unsigned char* buffer,
unsigned len );
84 void save(
unsigned char* buffer );
88 std::vector<unsigned long> data;
89 AllocTable(
const AllocTable& );
90 AllocTable& operator=(
const AllocTable& );
109 static const unsigned End;
112 unsigned entryCount();
113 DirEntry* entry(
unsigned index );
114 DirEntry* entry(
const std::string& name,
bool create=
false );
115 int indexOf( DirEntry* e );
116 int parent(
unsigned index );
117 std::string fullName(
unsigned index );
118 std::vector<unsigned> children(
unsigned index );
119 void load(
unsigned char* buffer,
unsigned len );
120 void save(
unsigned char* buffer );
124 std::vector<DirEntry> entries;
125 DirTree(
const DirTree& );
126 DirTree& operator=(
const DirTree& );
133 std::string filename;
137 unsigned long filesize;
144 std::vector<unsigned long> sb_blocks;
146 std::list<Stream*> streams;
148 StorageIO( Storage* storage,
const char* filename );
157 unsigned long loadBigBlocks( std::vector<unsigned long> blocks,
unsigned char* buffer,
unsigned long maxlen );
159 unsigned long loadBigBlock(
unsigned long block,
unsigned char* buffer,
unsigned long maxlen );
161 unsigned long loadSmallBlocks( std::vector<unsigned long> blocks,
unsigned char* buffer,
unsigned long maxlen );
163 unsigned long loadSmallBlock(
unsigned long block,
unsigned char* buffer,
unsigned long maxlen );
165 StreamIO* streamIO(
const std::string& name );
169 StorageIO(
const StorageIO& );
170 StorageIO& operator=(
const StorageIO& );
179 std::string fullName;
183 StreamIO( StorageIO* io, DirEntry* entry );
185 unsigned long size();
186 void seek(
unsigned long pos );
187 unsigned long tell();
189 unsigned long read(
unsigned char* data,
unsigned long maxlen );
190 unsigned long read(
unsigned long pos,
unsigned char* data,
unsigned long maxlen );
194 std::vector<unsigned long> blocks;
197 StreamIO(
const StreamIO& );
198 StreamIO& operator=(
const StreamIO& );
204 unsigned char* cache_data;
205 unsigned long cache_size;
206 unsigned long cache_pos;
214static inline unsigned long readU16(
const unsigned char* ptr )
216 return ptr[0]+(ptr[1]<<8);
219static inline unsigned long readU32(
const unsigned char* ptr )
221 return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
224static inline void writeU16(
unsigned char* ptr,
unsigned long data )
226 ptr[0] = (
unsigned char)(data & 0xff);
227 ptr[1] = (
unsigned char)((data >> 8) & 0xff);
230static inline void writeU32(
unsigned char* ptr,
unsigned long data )
232 ptr[0] = (
unsigned char)(data & 0xff);
233 ptr[1] = (
unsigned char)((data >> 8) & 0xff);
234 ptr[2] = (
unsigned char)((data >> 16) & 0xff);
235 ptr[3] = (
unsigned char)((data >> 24) & 0xff);
238static const unsigned char pole_magic[] =
239 { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
255 for(
unsigned i = 0; i < 8; i++ )
256 id[i] = pole_magic[i];
257 for(
unsigned i=0; i<109; i++ )
258 bb_blocks[i] = AllocTable::Avail;
263 if( threshold != 4096 )
return false;
264 if( num_bat == 0 )
return false;
265 if( (num_bat > 109) && (num_bat > (num_mbat * 127) + 109))
return false;
266 if( (num_bat < 109) && (num_mbat != 0) )
return false;
267 if( s_shift > b_shift )
return false;
268 if( b_shift <= 6 )
return false;
269 if( b_shift >=31 )
return false;
274void Header::load(
const unsigned char* buffer )
276 b_shift = readU16( buffer + 0x1e );
277 s_shift = readU16( buffer + 0x20 );
278 num_bat = readU32( buffer + 0x2c );
279 dirent_start = readU32( buffer + 0x30 );
280 threshold = readU32( buffer + 0x38 );
281 sbat_start = readU32( buffer + 0x3c );
282 num_sbat = readU32( buffer + 0x40 );
283 mbat_start = readU32( buffer + 0x44 );
284 num_mbat = readU32( buffer + 0x48 );
286 for(
unsigned i = 0; i < 8; i++ )
288 for(
unsigned i=0; i<109; i++ )
289 bb_blocks[i] = readU32( buffer + 0x4C+i*4 );
292void Header::save(
unsigned char* buffer )
294 memset( buffer, 0, 0x4c );
295 memcpy( buffer, pole_magic, 8 );
296 writeU32( buffer + 8, 0 );
297 writeU32( buffer + 12, 0 );
298 writeU32( buffer + 16, 0 );
299 writeU16( buffer + 24, 0x003e );
300 writeU16( buffer + 26, 3 );
301 writeU16( buffer + 28, 0xfffe );
302 writeU16( buffer + 0x1e, b_shift );
303 writeU16( buffer + 0x20, s_shift );
304 writeU32( buffer + 0x2c, num_bat );
305 writeU32( buffer + 0x30, dirent_start );
306 writeU32( buffer + 0x38, threshold );
307 writeU32( buffer + 0x3c, sbat_start );
308 writeU32( buffer + 0x40, num_sbat );
309 writeU32( buffer + 0x44, mbat_start );
310 writeU32( buffer + 0x48, num_mbat );
312 for(
unsigned i=0; i<109; i++ )
313 writeU32( buffer + 0x4C+i*4, bb_blocks[i] );
318 std::cout << std::endl;
319 std::cout <<
"b_shift " << b_shift << std::endl;
320 std::cout <<
"s_shift " << s_shift << std::endl;
321 std::cout <<
"num_bat " << num_bat << std::endl;
322 std::cout <<
"dirent_start " << dirent_start << std::endl;
323 std::cout <<
"threshold " << threshold << std::endl;
324 std::cout <<
"sbat_start " << sbat_start << std::endl;
325 std::cout <<
"num_sbat " << num_sbat << std::endl;
326 std::cout <<
"mbat_start " << mbat_start << std::endl;
327 std::cout <<
"num_mbat " << num_mbat << std::endl;
329 unsigned s = (num_bat<=109) ? num_bat : 109;
330 std::cout <<
"bat blocks: ";
331 for(
unsigned i = 0; i < s; i++ )
332 std::cout << bb_blocks[i] <<
" ";
333 std::cout << std::endl;
338const unsigned AllocTable::Avail = 0xffffffff;
339const unsigned AllocTable::Eof = 0xfffffffe;
340const unsigned AllocTable::Bat = 0xfffffffd;
341const unsigned AllocTable::MetaBat = 0xfffffffc;
343AllocTable::AllocTable()
350unsigned long AllocTable::count()
355void AllocTable::resize(
unsigned long newsize )
357 unsigned oldsize = data.size();
358 data.resize( newsize );
359 if( newsize > oldsize )
360 for(
unsigned i = oldsize; i<newsize; i++ )
365void AllocTable::preserve(
unsigned long n )
367 std::vector<unsigned long> pre;
368 for(
unsigned i=0; i < n; i++ )
369 pre.push_back( unused() );
372unsigned long AllocTable::operator[](
unsigned long index )
374 unsigned long result;
375 result = data[index];
379void AllocTable::set(
unsigned long index,
unsigned long value )
381 if( index >= count() ) resize( index + 1);
382 data[ index ] = value;
385void AllocTable::setChain( std::vector<unsigned long> chain )
389 for(
unsigned i=0; i<chain.size()-1; i++ )
390 set( chain[i], chain[i+1] );
391 set( chain[ chain.size()-1 ], AllocTable::Eof );
396std::vector<unsigned long> AllocTable::follow(
unsigned long start )
398 std::vector<unsigned long> chain;
400 if( start >= count() )
return chain;
402 unsigned long p = start;
405 if( p == (
unsigned long)Eof )
break;
406 if( p == (
unsigned long)Bat )
break;
407 if( p == (
unsigned long)MetaBat )
break;
408 if( p >= count() )
break;
409 chain.push_back( p );
410 if( data[p] >= count() )
break;
417unsigned AllocTable::unused()
420 for(
unsigned i = 0; i < data.size(); i++ )
421 if( data[i] == Avail )
425 unsigned block = data.size();
426 resize( data.size()+10 );
430void AllocTable::load(
const unsigned char* buffer,
unsigned len )
433 for(
unsigned i = 0; i < count(); i++ )
434 set( i, readU32( buffer + i*4 ) );
438unsigned AllocTable::size()
443void AllocTable::save(
unsigned char* buffer )
445 for(
unsigned i = 0; i < count(); i++ )
446 writeU32( buffer + i*4, data[i] );
449void AllocTable::debug()
451 std::cout <<
"block size " << data.size() << std::endl;
452 for(
unsigned i=0; i< data.size(); i++ )
454 if( data[i] == Avail )
continue;
455 std::cout << i <<
": ";
456 if( data[i] == Eof ) std::cout <<
"[eof]";
457 else if( data[i] == Bat ) std::cout <<
"[bat]";
458 else if( data[i] == MetaBat ) std::cout <<
"[metabat]";
459 else std::cout << data[i];
460 std::cout << std::endl;
466const unsigned DirTree::End = 0xffffffff;
477 entries[0].valid =
true;
478 entries[0].name =
"Root Entry";
479 entries[0].dir =
true;
481 entries[0].start = End;
482 entries[0].prev = End;
483 entries[0].next = End;
484 entries[0].child = End;
487unsigned DirTree::entryCount()
489 return entries.size();
492DirEntry* DirTree::entry(
unsigned index )
494 if( index >= entryCount() )
return (DirEntry*) 0;
495 return &entries[ index ];
498int DirTree::indexOf( DirEntry* e )
500 for(
unsigned i = 0; i < entryCount(); i++ )
501 if( entry( i ) == e )
return i;
506int DirTree::parent(
unsigned index )
510 for(
unsigned j=0; j<entryCount(); j++ )
512 std::vector<unsigned> chi = children( j );
513 for(
unsigned i=0; i<chi.size();i++ )
514 if( chi[i] == index )
521std::string DirTree::fullName(
unsigned index )
524 if( index == 0 )
return "/";
526 std::string result = entry( index )->name;
527 result.insert( 0,
"/" );
528 int p = parent( index );
529 DirEntry * _entry = 0;
533 if (_entry->dir && _entry->valid)
535 result.insert( 0, _entry->name);
536 result.insert( 0,
"/" );
540 if( index <= 0 )
break;
548DirEntry* DirTree::entry(
const std::string& name,
bool create )
550 if( !name.length() )
return (DirEntry*)0;
553 if( name ==
"/" )
return entry( 0 );
557 std::list<std::string> names;
558 std::string::size_type start = 0, end = 0;
559 if( name[0] ==
'/' ) start++;
560 while( start < name.length() )
562 end = name.find_first_of(
'/', start );
563 if( end == std::string::npos ) end = name.length();
564 names.push_back( name.substr( start, end-start ) );
572 std::list<std::string>::iterator it;
574 for( it = names.begin(); it != names.end(); ++it )
577 std::vector<unsigned> chi = children( index );
579 for(
unsigned i = 0; i < chi.size(); i++ )
581 DirEntry* ce = entry( chi[i] );
583 if( ce->valid && ( ce->name.length()>1 ) )
584 if( ce->name == *it )
589 if( child > 0 ) index = child;
593 if( !create )
return (DirEntry*)0;
596 unsigned parent = index;
597 entries.push_back( DirEntry() );
598 index = entryCount()-1;
599 DirEntry* e = entry( index );
607 e->next = entry(parent)->child;
608 entry(parent)->child = index;
612 return entry( index );
616void dirtree_find_siblings( DirTree* dirtree, std::vector<unsigned>& result,
619 DirEntry* e = dirtree->entry( index );
621 if( !e->valid )
return;
624 for(
unsigned i = 0; i < result.size(); i++ )
625 if( result[i] == index )
return;
628 result.push_back( index );
631 unsigned prev = e->prev;
632 if( ( prev > 0 ) && ( prev < dirtree->entryCount() ) )
634 for(
unsigned i = 0; i < result.size(); i++ )
635 if( result[i] == prev ) prev = 0;
636 if( prev ) dirtree_find_siblings( dirtree, result, prev );
640 unsigned next = e->next;
641 if( ( next > 0 ) && ( next < dirtree->entryCount() ) )
643 for(
unsigned i = 0; i < result.size(); i++ )
644 if( result[i] == next ) next = 0;
645 if( next ) dirtree_find_siblings( dirtree, result, next );
649std::vector<unsigned> DirTree::children(
unsigned index )
651 std::vector<unsigned> result;
653 DirEntry* e = entry( index );
654 if( e )
if( e->valid && e->child < entryCount() )
655 dirtree_find_siblings(
this, result, e->child );
660void DirTree::load(
unsigned char* buffer,
unsigned size )
664 for(
unsigned i = 0; i < size/128; i++ )
666 unsigned p = i * 128;
669 unsigned prefix = 32;
673 int name_len = readU16( buffer + 0x40+p );
674 if( name_len > 64 ) name_len = 64;
675 for(
int j=0; ( buffer[j+p]) && (j<name_len); j+= 2 )
676 name.append( 1, buffer[j+p] );
686 unsigned type = buffer[ 0x42 + p];
691 e.start = readU32( buffer + 0x74+p );
692 e.size = readU32( buffer + 0x78+p );
693 e.prev = readU32( buffer + 0x44+p );
694 e.next = readU32( buffer + 0x48+p );
695 e.child = readU32( buffer + 0x4C+p );
699 if( (type != 2) && (type != 1 ) && (type != 5 ) ) e.valid =
false;
700 if( name_len < 1 ) e.valid =
false;
702 entries.push_back( e );
707unsigned DirTree::size()
709 return entryCount() * 128;
712void DirTree::save(
unsigned char* buffer )
714 memset( buffer, 0, size() );
717 DirEntry* root = entry( 0 );
718 std::string name =
"Root Entry";
719 for(
unsigned j = 0; j < name.length(); j++ )
720 buffer[ j*2 ] = name[j];
721 writeU16( buffer + 0x40, name.length()*2 + 2 );
722 writeU32( buffer + 0x74, 0xffffffff );
723 writeU32( buffer + 0x78, 0 );
724 writeU32( buffer + 0x44, 0xffffffff );
725 writeU32( buffer + 0x48, 0xffffffff );
726 writeU32( buffer + 0x4c, root->child );
730 for(
unsigned i = 1; i < entryCount(); i++ )
732 DirEntry* e = entry( i );
736 e->start = 0xffffffff;
741 std::string name = e->name;
742 if( name.length() > 32 )
743 name.erase( 32, name.length() );
746 for(
unsigned j = 0; j < name.length(); j++ )
747 buffer[ i*128 + j*2 ] = name[j];
749 writeU16( buffer + i*128 + 0x40, name.length()*2 + 2 );
750 writeU32( buffer + i*128 + 0x74, e->start );
751 writeU32( buffer + i*128 + 0x78, e->size );
752 writeU32( buffer + i*128 + 0x44, e->prev );
753 writeU32( buffer + i*128 + 0x48, e->next );
754 writeU32( buffer + i*128 + 0x4c, e->child );
755 buffer[ i*128 + 0x42 ] = e->dir ? 1 : 2;
756 buffer[ i*128 + 0x43 ] = 1;
762 for(
unsigned i = 0; i < entryCount(); i++ )
764 DirEntry* e = entry( i );
766 std::cout << i <<
": ";
767 if( !e->valid ) std::cout <<
"INVALID ";
768 std::cout << e->name <<
" ";
769 if( e->dir ) std::cout <<
"(Dir) ";
770 else std::cout <<
"(File) ";
771 std::cout << e->size <<
" ";
772 std::cout <<
"s:" << e->start <<
" ";
774 if( e->child == End ) std::cout <<
"-";
else std::cout << e->child;
776 if( e->prev == End ) std::cout <<
"-";
else std::cout << e->prev;
778 if( e->next == End ) std::cout <<
"-";
else std::cout << e->next;
780 std::cout << std::endl;
786StorageIO::StorageIO( Storage* st,
const char* fname )
790 result = Storage::Ok;
793 header =
new Header();
794 dirtree =
new DirTree();
795 bbat =
new AllocTable();
796 sbat =
new AllocTable();
799 bbat->blockSize = 1 << header->b_shift;
800 sbat->blockSize = 1 << header->s_shift;
803StorageIO::~StorageIO()
805 if( opened ) close();
812bool StorageIO::open()
815 if( opened ) close();
819 return result == Storage::Ok;
822void StorageIO::load()
824 unsigned char* buffer = 0;
825 unsigned long buflen = 0;
826 std::vector<unsigned long> blocks;
829 result = Storage::OpenFailed;
830 file.open( filename.c_str(), std::ios::binary | std::ios::in );
831 if( !file.good() )
return;
834 file.seekg( 0, std::ios::end );
835 filesize = file.tellg();
838 buffer =
new unsigned char[512];
840 file.read( (
char*)buffer, 512 );
841 header->load( buffer );
845 result = Storage::NotOLE;
846 for(
unsigned i=0; i<8; i++ )
847 if( header->id[i] != pole_magic[i] )
851 result = Storage::BadOLE;
852 if( !header->valid() )
return;
853 if( header->threshold != 4096 )
return;
856 bbat->blockSize = 1 << header->b_shift;
857 sbat->blockSize = 1 << header->s_shift;
862 blocks.resize( header->num_bat );
863 for(
unsigned i = 0; i < 109; i++ )
864 if( i >= header->num_bat )
break;
865 else blocks[i] = header->bb_blocks[i];
866 if( (header->num_bat > 109) && (header->num_mbat > 0) )
868 unsigned char* buffer2 =
new unsigned char[ bbat->blockSize ];
870 unsigned mblock = header->mbat_start;
871 for(
unsigned r = 0; r < header->num_mbat; r++ )
873 loadBigBlock( mblock, buffer2, bbat->blockSize );
874 for(
unsigned s=0; s < bbat->blockSize-4; s+=4 )
876 if( k >= header->num_bat )
break;
877 else blocks[k++] = readU32( buffer2 + s );
879 mblock = readU32( buffer2 + bbat->blockSize-4 );
885 buflen = blocks.size()*bbat->blockSize;
888 buffer =
new unsigned char[ buflen ];
889 loadBigBlocks( blocks, buffer, buflen );
890 bbat->load( buffer, buflen );
896 blocks = bbat->follow( header->sbat_start );
897 buflen = blocks.size()*bbat->blockSize;
900 buffer =
new unsigned char[ buflen ];
901 loadBigBlocks( blocks, buffer, buflen );
902 sbat->load( buffer, buflen );
908 blocks = bbat->follow( header->dirent_start );
909 buflen = blocks.size()*bbat->blockSize;
910 buffer =
new unsigned char[ buflen ];
911 loadBigBlocks( blocks, buffer, buflen );
912 dirtree->load( buffer, buflen );
913 unsigned sb_start = readU32( buffer + 0x74 );
917 sb_blocks = bbat->follow( sb_start );
928 result = Storage::Ok;
932void StorageIO::create()
936 file.open( filename.c_str(), std::ios::out|std::ios::binary );
939 std::cerr <<
"Can't create " << filename << std::endl;
940 result = Storage::OpenFailed;
946 result = Storage::Ok;
949void StorageIO::flush()
958void StorageIO::close()
960 if( !opened )
return;
965 std::list<Stream*>::iterator it;
966 for( it = streams.begin(); it != streams.end(); ++it )
970StreamIO* StorageIO::streamIO(
const std::string& name )
973 if( !name.length() )
return (StreamIO*)0;
976 DirEntry* entry = dirtree->entry( name );
978 if( !entry )
return (StreamIO*)0;
980 if( entry->dir )
return (StreamIO*)0;
982 StreamIO* result =
new StreamIO(
this, entry );
983 result->fullName = name;
988unsigned long StorageIO::loadBigBlocks( std::vector<unsigned long> blocks,
989 unsigned char* data,
unsigned long maxlen )
992 if( !data )
return 0;
993 if( !file.good() )
return 0;
994 if( blocks.size() < 1 )
return 0;
995 if( maxlen == 0 )
return 0;
998 unsigned long bytes = 0;
999 for(
unsigned long i=0; (i < blocks.size() ) & ( bytes<maxlen ); i++ )
1001 unsigned long block = blocks[i];
1002 unsigned long pos = bbat->blockSize * ( block+1 );
1003 unsigned long p = (bbat->blockSize < maxlen-bytes) ? bbat->blockSize : maxlen-bytes;
1004 if( pos + p > filesize ) p = filesize - pos;
1006 file.read( (
char*)data + bytes, p );
1013unsigned long StorageIO::loadBigBlock(
unsigned long block,
1014 unsigned char* data,
unsigned long maxlen )
1017 if( !data )
return 0;
1018 if( !file.good() )
return 0;
1021 std::vector<unsigned long> blocks;
1023 blocks[ 0 ] = block;
1025 return loadBigBlocks( blocks, data, maxlen );
1029unsigned long StorageIO::loadSmallBlocks( std::vector<unsigned long> blocks,
1030 unsigned char* data,
unsigned long maxlen )
1033 if( !data )
return 0;
1034 if( !file.good() )
return 0;
1035 if( blocks.size() < 1 )
return 0;
1036 if( maxlen == 0 )
return 0;
1039 unsigned char* buf =
new unsigned char[ bbat->blockSize ];
1042 unsigned long bytes = 0;
1043 for(
unsigned long i=0; ( i<blocks.size() ) & ( bytes<maxlen ); i++ )
1045 unsigned long block = blocks[i];
1048 unsigned long pos = block * sbat->blockSize;
1049 unsigned long bbindex = pos / bbat->blockSize;
1050 if( bbindex >= sb_blocks.size() )
break;
1052 loadBigBlock( sb_blocks[ bbindex ], buf, bbat->blockSize );
1055 unsigned offset = pos % bbat->blockSize;
1056 unsigned long p = (maxlen-bytes < bbat->blockSize-offset ) ? maxlen-bytes : bbat->blockSize-offset;
1057 p = (sbat->blockSize<p ) ? sbat->blockSize : p;
1058 memcpy( data + bytes, buf + offset, p );
1067unsigned long StorageIO::loadSmallBlock(
unsigned long block,
1068 unsigned char* data,
unsigned long maxlen )
1071 if( !data )
return 0;
1072 if( !file.good() )
return 0;
1075 std::vector<unsigned long> blocks;
1077 blocks.assign( 1, block );
1079 return loadSmallBlocks( blocks, data, maxlen );
1084StreamIO::StreamIO( StorageIO* s, DirEntry* e)
1093 if( entry->size >= io->header->threshold )
1094 blocks = io->bbat->follow( entry->start );
1096 blocks = io->sbat->follow( entry->start );
1101 cache_data =
new unsigned char[cache_size];
1106StreamIO::~StreamIO()
1108 delete[] cache_data;
1111void StreamIO::seek(
unsigned long pos )
1116unsigned long StreamIO::tell()
1121int StreamIO::getch()
1124 if( m_pos > entry->size )
return -1;
1127 if( !cache_size || ( m_pos < cache_pos ) ||
1128 ( m_pos >= cache_pos + cache_size ) )
1132 if( !cache_size )
return -1;
1134 int data = cache_data[m_pos - cache_pos];
1140unsigned long StreamIO::read(
unsigned long pos,
unsigned char* data,
unsigned long maxlen )
1143 if( !data )
return 0;
1144 if( maxlen == 0 )
return 0;
1146 unsigned long totalbytes = 0;
1148 if ( entry->size < io->header->threshold )
1151 unsigned long index = pos / io->sbat->blockSize;
1153 if( index >= blocks.size() )
return 0;
1155 unsigned char* buf =
new unsigned char[ io->sbat->blockSize ];
1156 unsigned long offset = pos % io->sbat->blockSize;
1157 while( totalbytes < maxlen )
1159 if( index >= blocks.size() )
break;
1160 io->loadSmallBlock( blocks[index], buf, io->bbat->blockSize );
1161 unsigned long count = io->sbat->blockSize - offset;
1162 if( count > maxlen-totalbytes ) count = maxlen-totalbytes;
1163 memcpy( data+totalbytes, buf + offset, count );
1164 totalbytes += count;
1174 unsigned long index = pos / io->bbat->blockSize;
1176 if( index >= blocks.size() )
return 0;
1178 unsigned char* buf =
new unsigned char[ io->bbat->blockSize ];
1179 unsigned long offset = pos % io->bbat->blockSize;
1180 while( totalbytes < maxlen )
1182 if( index >= blocks.size() )
break;
1183 io->loadBigBlock( blocks[index], buf, io->bbat->blockSize );
1184 unsigned long count = io->bbat->blockSize - offset;
1185 if( count > maxlen-totalbytes ) count = maxlen-totalbytes;
1186 memcpy( data+totalbytes, buf + offset, count );
1187 totalbytes += count;
1198unsigned long StreamIO::read(
unsigned char* data,
unsigned long maxlen )
1200 unsigned long bytes = read( tell(), data, maxlen );
1205void StreamIO::updateCache()
1208 if( !cache_data )
return;
1210 cache_pos = m_pos - ( m_pos % cache_size );
1211 unsigned long bytes = cache_size;
1212 if( cache_pos + bytes > entry->size ) bytes = entry->size - cache_pos;
1213 cache_size = read( cache_pos, cache_data, bytes );
1219Storage::Storage(
const char* filename )
1221 io =
new StorageIO(
this, filename );
1229int Storage::result()
1239void Storage::close()
1244std::list<std::string> Storage::entries(
const std::string& path )
1246 std::list<std::string> result;
1247 DirTree* dt = io->dirtree;
1248 DirEntry* e = dt->entry( path,
false );
1251 unsigned parent = dt->indexOf( e );
1252 std::vector<unsigned> children = dt->children( parent );
1253 for(
unsigned i = 0; i < children.size(); i++ )
1254 result.push_back( dt->entry( children[i] )->name );
1260bool Storage::isDirectory(
const std::string& name )
1262 DirEntry* e = io->dirtree->entry( name,
false );
1263 return e ? e->dir :
false;
1268Stream::Stream( Storage* storage,
const std::string& name )
1270 io = storage->io->streamIO( name );
1279std::string Stream::fullName()
1281 return io ? io->fullName : std::string();
1284unsigned long Stream::tell()
1286 return io ? io->tell() : 0;
1289void Stream::seek(
unsigned long newpos )
1291 if( io ) io->seek( newpos );
1294unsigned long Stream::size()
1296 return io ? io->entry->size : 0;
1301 return io ? io->getch() : 0;
1304unsigned long Stream::read(
unsigned char* data,
unsigned long maxlen )
1306 return io ? io->read( data, maxlen ) : 0;
1311 return io ? io->eof :
false;
1316 return io ? io->fail :
true;