52 unsigned dirent_start;
58 unsigned long bb_blocks[109];
62 void load(
const unsigned char* buffer );
63 void save(
unsigned char* buffer );
70 static const unsigned Eof;
71 static const unsigned Avail;
72 static const unsigned Bat;
73 static const unsigned MetaBat;
77 unsigned long count();
78 void resize(
unsigned long newsize );
79 void preserve(
unsigned long n );
80 void set(
unsigned long index,
unsigned long val );
82 void setChain( std::vector<unsigned long> );
83 std::vector<unsigned long> follow(
unsigned long start );
84 unsigned long operator[](
unsigned long index );
85 void load(
const unsigned char* buffer,
unsigned len );
86 void save(
unsigned char* buffer );
90 std::vector<unsigned long> data;
91 AllocTable(
const AllocTable& );
92 AllocTable& operator=(
const AllocTable& );
111 static const unsigned End;
114 unsigned entryCount();
115 DirEntry* entry(
unsigned index );
116 DirEntry* entry(
const std::string& name,
bool create=
false );
117 int indexOf( DirEntry* e );
118 int parent(
unsigned index );
119 std::string fullName(
unsigned index );
120 std::vector<unsigned> children(
unsigned index );
121 void load(
unsigned char* buffer,
unsigned len );
122 void save(
unsigned char* buffer );
126 std::vector<DirEntry> entries;
127 DirTree(
const DirTree& );
128 DirTree& operator=(
const DirTree& );
135 std::string filename;
139 unsigned long filesize;
146 std::vector<unsigned long> sb_blocks;
148 std::list<Stream*> streams;
150 StorageIO( Storage* storage,
const char* filename );
159 unsigned long loadBigBlocks( std::vector<unsigned long> blocks,
unsigned char* buffer,
unsigned long maxlen );
161 unsigned long loadBigBlock(
unsigned long block,
unsigned char* buffer,
unsigned long maxlen );
163 unsigned long loadSmallBlocks( std::vector<unsigned long> blocks,
unsigned char* buffer,
unsigned long maxlen );
165 unsigned long loadSmallBlock(
unsigned long block,
unsigned char* buffer,
unsigned long maxlen );
167 StreamIO* streamIO(
const std::string& name );
171 StorageIO(
const StorageIO& );
172 StorageIO& operator=(
const StorageIO& );
181 std::string fullName;
185 StreamIO( StorageIO* io, DirEntry* entry );
187 unsigned long size();
188 void seek(
unsigned long pos );
189 unsigned long tell();
191 unsigned long read(
unsigned char* data,
unsigned long maxlen );
192 unsigned long read(
unsigned long pos,
unsigned char* data,
unsigned long maxlen );
196 std::vector<unsigned long> blocks;
199 StreamIO(
const StreamIO& );
200 StreamIO& operator=(
const StreamIO& );
206 unsigned char* cache_data;
207 unsigned long cache_size;
208 unsigned long cache_pos;
216static inline unsigned long readU16(
const unsigned char* ptr )
218 return ptr[0]+(ptr[1]<<8);
221static inline unsigned long readU32(
const unsigned char* ptr )
223 return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
226static inline void writeU16(
unsigned char* ptr,
unsigned long data )
228 ptr[0] = (
unsigned char)(data & 0xff);
229 ptr[1] = (
unsigned char)((data >> 8) & 0xff);
232static inline void writeU32(
unsigned char* ptr,
unsigned long data )
234 ptr[0] = (
unsigned char)(data & 0xff);
235 ptr[1] = (
unsigned char)((data >> 8) & 0xff);
236 ptr[2] = (
unsigned char)((data >> 16) & 0xff);
237 ptr[3] = (
unsigned char)((data >> 24) & 0xff);
240static const unsigned char pole_magic[] =
241 { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
257 for(
unsigned i = 0; i < 8; i++ )
258 id[i] = pole_magic[i];
259 for(
unsigned i=0; i<109; i++ )
260 bb_blocks[i] = AllocTable::Avail;
265 if( threshold != 4096 )
return false;
266 if( num_bat == 0 )
return false;
267 if( (num_bat > 109) && (num_bat > (num_mbat * 127) + 109))
return false;
268 if( (num_bat < 109) && (num_mbat != 0) )
return false;
269 if( s_shift > b_shift )
return false;
270 if( b_shift <= 6 )
return false;
271 if( b_shift >=31 )
return false;
276void Header::load(
const unsigned char* buffer )
278 b_shift = readU16( buffer + 0x1e );
279 s_shift = readU16( buffer + 0x20 );
280 num_bat = readU32( buffer + 0x2c );
281 dirent_start = readU32( buffer + 0x30 );
282 threshold = readU32( buffer + 0x38 );
283 sbat_start = readU32( buffer + 0x3c );
284 num_sbat = readU32( buffer + 0x40 );
285 mbat_start = readU32( buffer + 0x44 );
286 num_mbat = readU32( buffer + 0x48 );
288 for(
unsigned i = 0; i < 8; i++ )
290 for(
unsigned i=0; i<109; i++ )
291 bb_blocks[i] = readU32( buffer + 0x4C+i*4 );
294void Header::save(
unsigned char* buffer )
296 memset( buffer, 0, 0x4c );
297 memcpy( buffer, pole_magic, 8 );
298 writeU32( buffer + 8, 0 );
299 writeU32( buffer + 12, 0 );
300 writeU32( buffer + 16, 0 );
301 writeU16( buffer + 24, 0x003e );
302 writeU16( buffer + 26, 3 );
303 writeU16( buffer + 28, 0xfffe );
304 writeU16( buffer + 0x1e, b_shift );
305 writeU16( buffer + 0x20, s_shift );
306 writeU32( buffer + 0x2c, num_bat );
307 writeU32( buffer + 0x30, dirent_start );
308 writeU32( buffer + 0x38, threshold );
309 writeU32( buffer + 0x3c, sbat_start );
310 writeU32( buffer + 0x40, num_sbat );
311 writeU32( buffer + 0x44, mbat_start );
312 writeU32( buffer + 0x48, num_mbat );
314 for(
unsigned i=0; i<109; i++ )
315 writeU32( buffer + 0x4C+i*4, bb_blocks[i] );
320 std::cout << std::endl;
321 std::cout <<
"b_shift " << b_shift << std::endl;
322 std::cout <<
"s_shift " << s_shift << std::endl;
323 std::cout <<
"num_bat " << num_bat << std::endl;
324 std::cout <<
"dirent_start " << dirent_start << std::endl;
325 std::cout <<
"threshold " << threshold << std::endl;
326 std::cout <<
"sbat_start " << sbat_start << std::endl;
327 std::cout <<
"num_sbat " << num_sbat << std::endl;
328 std::cout <<
"mbat_start " << mbat_start << std::endl;
329 std::cout <<
"num_mbat " << num_mbat << std::endl;
331 unsigned s = (num_bat<=109) ? num_bat : 109;
332 std::cout <<
"bat blocks: ";
333 for(
unsigned i = 0; i < s; i++ )
334 std::cout << bb_blocks[i] <<
" ";
335 std::cout << std::endl;
340const unsigned AllocTable::Avail = 0xffffffff;
341const unsigned AllocTable::Eof = 0xfffffffe;
342const unsigned AllocTable::Bat = 0xfffffffd;
343const unsigned AllocTable::MetaBat = 0xfffffffc;
345AllocTable::AllocTable()
352unsigned long AllocTable::count()
357void AllocTable::resize(
unsigned long newsize )
359 unsigned oldsize = data.size();
360 data.resize( newsize );
361 if( newsize > oldsize )
362 for(
unsigned i = oldsize; i<newsize; i++ )
367void AllocTable::preserve(
unsigned long n )
369 std::vector<unsigned long> pre;
370 for(
unsigned i=0; i < n; i++ )
371 pre.push_back( unused() );
374unsigned long AllocTable::operator[](
unsigned long index )
376 unsigned long result;
377 result = data[index];
381void AllocTable::set(
unsigned long index,
unsigned long value )
383 if( index >= count() ) resize( index + 1);
384 data[ index ] = value;
387void AllocTable::setChain( std::vector<unsigned long> chain )
391 for(
unsigned i=0; i<chain.size()-1; i++ )
392 set( chain[i], chain[i+1] );
393 set( chain[ chain.size()-1 ], AllocTable::Eof );
398std::vector<unsigned long> AllocTable::follow(
unsigned long start )
400 std::vector<unsigned long> chain;
402 if( start >= count() )
return chain;
404 unsigned long p = start;
407 if( p == (
unsigned long)Eof )
break;
408 if( p == (
unsigned long)Bat )
break;
409 if( p == (
unsigned long)MetaBat )
break;
410 if( p >= count() )
break;
411 chain.push_back( p );
412 if( data[p] >= count() )
break;
419unsigned AllocTable::unused()
422 for(
unsigned i = 0; i < data.size(); i++ )
423 if( data[i] == Avail )
427 unsigned block = data.size();
428 resize( data.size()+10 );
432void AllocTable::load(
const unsigned char* buffer,
unsigned len )
435 for(
unsigned i = 0; i < count(); i++ )
436 set( i, readU32( buffer + i*4 ) );
440unsigned AllocTable::size()
445void AllocTable::save(
unsigned char* buffer )
447 for(
unsigned i = 0; i < count(); i++ )
448 writeU32( buffer + i*4, data[i] );
451void AllocTable::debug()
453 std::cout <<
"block size " << data.size() << std::endl;
454 for(
unsigned i=0; i< data.size(); i++ )
456 if( data[i] == Avail )
continue;
457 std::cout << i <<
": ";
458 if( data[i] == Eof ) std::cout <<
"[eof]";
459 else if( data[i] == Bat ) std::cout <<
"[bat]";
460 else if( data[i] == MetaBat ) std::cout <<
"[metabat]";
461 else std::cout << data[i];
462 std::cout << std::endl;
468const unsigned DirTree::End = 0xffffffff;
479 entries[0].valid =
true;
480 entries[0].name =
"Root Entry";
481 entries[0].dir =
true;
483 entries[0].start = End;
484 entries[0].prev = End;
485 entries[0].next = End;
486 entries[0].child = End;
489unsigned DirTree::entryCount()
491 return entries.size();
494DirEntry* DirTree::entry(
unsigned index )
496 if( index >= entryCount() )
return (DirEntry*) 0;
497 return &entries[ index ];
500int DirTree::indexOf( DirEntry* e )
502 for(
unsigned i = 0; i < entryCount(); i++ )
503 if( entry( i ) == e )
return i;
508int DirTree::parent(
unsigned index )
512 for(
unsigned j=0; j<entryCount(); j++ )
514 std::vector<unsigned> chi = children( j );
515 for(
unsigned i=0; i<chi.size();i++ )
516 if( chi[i] == index )
523std::string DirTree::fullName(
unsigned index )
526 if( index == 0 )
return "/";
528 std::string result = entry( index )->name;
529 result.insert( 0,
"/" );
530 int p = parent( index );
531 DirEntry * _entry = 0;
535 if (_entry->dir && _entry->valid)
537 result.insert( 0, _entry->name);
538 result.insert( 0,
"/" );
542 if( index <= 0 )
break;
550DirEntry* DirTree::entry(
const std::string& name,
bool create )
552 if( !name.length() )
return (DirEntry*)0;
555 if( name ==
"/" )
return entry( 0 );
559 std::list<std::string> names;
560 std::string::size_type start = 0, end = 0;
561 if( name[0] ==
'/' ) start++;
562 while( start < name.length() )
564 end = name.find_first_of(
'/', start );
565 if( end == std::string::npos ) end = name.length();
566 names.push_back( name.substr( start, end-start ) );
574 std::list<std::string>::iterator it;
576 for( it = names.begin(); it != names.end(); ++it )
579 std::vector<unsigned> chi = children( index );
581 for(
unsigned i = 0; i < chi.size(); i++ )
583 DirEntry* ce = entry( chi[i] );
585 if( ce->valid && ( ce->name.length()>1 ) )
586 if( ce->name == *it )
591 if( child > 0 ) index = child;
595 if( !create )
return (DirEntry*)0;
598 unsigned parent = index;
599 entries.push_back( DirEntry() );
600 index = entryCount()-1;
601 DirEntry* e = entry( index );
609 e->next = entry(parent)->child;
610 entry(parent)->child = index;
614 return entry( index );
618void dirtree_find_siblings( DirTree* dirtree, std::vector<unsigned>& result,
621 DirEntry* e = dirtree->entry( index );
623 if( !e->valid )
return;
626 for(
unsigned i = 0; i < result.size(); i++ )
627 if( result[i] == index )
return;
630 result.push_back( index );
633 unsigned prev = e->prev;
634 if( ( prev > 0 ) && ( prev < dirtree->entryCount() ) )
636 for(
unsigned i = 0; i < result.size(); i++ )
637 if( result[i] == prev ) prev = 0;
638 if( prev ) dirtree_find_siblings( dirtree, result, prev );
642 unsigned next = e->next;
643 if( ( next > 0 ) && ( next < dirtree->entryCount() ) )
645 for(
unsigned i = 0; i < result.size(); i++ )
646 if( result[i] == next ) next = 0;
647 if( next ) dirtree_find_siblings( dirtree, result, next );
651std::vector<unsigned> DirTree::children(
unsigned index )
653 std::vector<unsigned> result;
655 DirEntry* e = entry( index );
656 if( e )
if( e->valid && e->child < entryCount() )
657 dirtree_find_siblings(
this, result, e->child );
662void DirTree::load(
unsigned char* buffer,
unsigned size )
666 for(
unsigned i = 0; i < size/128; i++ )
668 unsigned p = i * 128;
671 unsigned prefix = 32;
675 int name_len = readU16( buffer + 0x40+p );
676 if( name_len > 64 ) name_len = 64;
677 for(
int j=0; ( buffer[j+p]) && (j<name_len); j+= 2 )
678 name.append( 1, buffer[j+p] );
688 unsigned type = buffer[ 0x42 + p];
693 e.start = readU32( buffer + 0x74+p );
694 e.size = readU32( buffer + 0x78+p );
695 e.prev = readU32( buffer + 0x44+p );
696 e.next = readU32( buffer + 0x48+p );
697 e.child = readU32( buffer + 0x4C+p );
701 if( (type != 2) && (type != 1 ) && (type != 5 ) ) e.valid =
false;
702 if( name_len < 1 ) e.valid =
false;
704 entries.push_back( e );
709unsigned DirTree::size()
711 return entryCount() * 128;
714void DirTree::save(
unsigned char* buffer )
716 memset( buffer, 0, size() );
719 DirEntry* root = entry( 0 );
720 std::string name =
"Root Entry";
721 for(
unsigned j = 0; j < name.length(); j++ )
722 buffer[ j*2 ] = name[j];
723 writeU16( buffer + 0x40, name.length()*2 + 2 );
724 writeU32( buffer + 0x74, 0xffffffff );
725 writeU32( buffer + 0x78, 0 );
726 writeU32( buffer + 0x44, 0xffffffff );
727 writeU32( buffer + 0x48, 0xffffffff );
728 writeU32( buffer + 0x4c, root->child );
732 for(
unsigned i = 1; i < entryCount(); i++ )
734 DirEntry* e = entry( i );
738 e->start = 0xffffffff;
743 std::string name = e->name;
744 if( name.length() > 32 )
745 name.erase( 32, name.length() );
748 for(
unsigned j = 0; j < name.length(); j++ )
749 buffer[ i*128 + j*2 ] = name[j];
751 writeU16( buffer + i*128 + 0x40, name.length()*2 + 2 );
752 writeU32( buffer + i*128 + 0x74, e->start );
753 writeU32( buffer + i*128 + 0x78, e->size );
754 writeU32( buffer + i*128 + 0x44, e->prev );
755 writeU32( buffer + i*128 + 0x48, e->next );
756 writeU32( buffer + i*128 + 0x4c, e->child );
757 buffer[ i*128 + 0x42 ] = e->dir ? 1 : 2;
758 buffer[ i*128 + 0x43 ] = 1;
764 for(
unsigned i = 0; i < entryCount(); i++ )
766 DirEntry* e = entry( i );
768 std::cout << i <<
": ";
769 if( !e->valid ) std::cout <<
"INVALID ";
770 std::cout << e->name <<
" ";
771 if( e->dir ) std::cout <<
"(Dir) ";
772 else std::cout <<
"(File) ";
773 std::cout << e->size <<
" ";
774 std::cout <<
"s:" << e->start <<
" ";
776 if( e->child == End ) std::cout <<
"-";
else std::cout << e->child;
778 if( e->prev == End ) std::cout <<
"-";
else std::cout << e->prev;
780 if( e->next == End ) std::cout <<
"-";
else std::cout << e->next;
782 std::cout << std::endl;
788StorageIO::StorageIO( Storage* st,
const char* fname )
792 result = Storage::Ok;
795 header =
new Header();
796 dirtree =
new DirTree();
797 bbat =
new AllocTable();
798 sbat =
new AllocTable();
801 bbat->blockSize = 1 << header->b_shift;
802 sbat->blockSize = 1 << header->s_shift;
805StorageIO::~StorageIO()
807 if( opened ) close();
814bool StorageIO::open()
817 if( opened ) close();
821 return result == Storage::Ok;
824void StorageIO::load()
826 unsigned char* buffer = 0;
827 unsigned long buflen = 0;
828 std::vector<unsigned long> blocks;
831 result = Storage::OpenFailed;
832 file.open( filename.c_str(), std::ios::binary | std::ios::in );
833 if( !file.good() )
return;
836 file.seekg( 0, std::ios::end );
837 filesize = file.tellg();
840 buffer =
new unsigned char[512];
842 file.read( (
char*)buffer, 512 );
843 header->load( buffer );
847 result = Storage::NotOLE;
848 for(
unsigned i=0; i<8; i++ )
849 if( header->id[i] != pole_magic[i] )
853 result = Storage::BadOLE;
854 if( !header->valid() )
return;
855 if( header->threshold != 4096 )
return;
858 bbat->blockSize = 1 << header->b_shift;
859 sbat->blockSize = 1 << header->s_shift;
864 blocks.resize( header->num_bat );
865 for(
unsigned i = 0; i < 109; i++ )
866 if( i >= header->num_bat )
break;
867 else blocks[i] = header->bb_blocks[i];
868 if( (header->num_bat > 109) && (header->num_mbat > 0) )
870 unsigned char* buffer2 =
new unsigned char[ bbat->blockSize ];
872 for(
unsigned r = 0; r < header->num_mbat; r++ )
874 loadBigBlock( header->mbat_start+r, buffer2, bbat->blockSize );
875 for(
unsigned s=0; s < bbat->blockSize; s+=4 )
877 if( k >= header->num_bat )
break;
878 else blocks[k++] = readU32( buffer2 + s );
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;