51 unsigned dirent_start;
57 unsigned long bb_blocks[109];
61 void load(
const unsigned char* buffer );
62 void save(
unsigned char* buffer );
69 static const unsigned Eof;
70 static const unsigned Avail;
71 static const unsigned Bat;
72 static const unsigned MetaBat;
76 unsigned long count();
77 void resize(
unsigned long newsize );
78 void preserve(
unsigned long n );
79 void set(
unsigned long index,
unsigned long val );
81 void setChain( std::vector<unsigned long> );
82 std::vector<unsigned long> follow(
unsigned long start );
83 unsigned long operator[](
unsigned long index );
84 void load(
const unsigned char* buffer,
unsigned len );
85 void save(
unsigned char* buffer );
89 std::vector<unsigned long> data;
90 AllocTable(
const AllocTable& );
91 AllocTable& operator=(
const AllocTable& );
110 static const unsigned End;
113 unsigned entryCount();
114 DirEntry* entry(
unsigned index );
115 DirEntry* entry(
const std::string& name,
bool create=
false );
116 int indexOf( DirEntry* e );
117 int parent(
unsigned index );
118 std::string fullName(
unsigned index );
119 std::vector<unsigned> children(
unsigned index );
120 void load(
unsigned char* buffer,
unsigned len );
121 void save(
unsigned char* buffer );
125 std::vector<DirEntry> entries;
126 DirTree(
const DirTree& );
127 DirTree& operator=(
const DirTree& );
134 std::string filename;
138 unsigned long filesize;
145 unsigned long lastBlockIndex;
146 unsigned char* lastBlockData;
148 std::vector<unsigned long> sb_blocks;
150 std::list<Stream*> streams;
152 StorageIO( Storage* storage,
const char* filename );
161 unsigned long loadBigBlocks( std::vector<unsigned long> blocks,
unsigned char* buffer,
unsigned long maxlen );
163 unsigned long loadBigBlock(
unsigned long block,
unsigned char* buffer,
unsigned long maxlen );
165 unsigned long loadSmallBlocks( std::vector<unsigned long> blocks,
unsigned char* buffer,
unsigned long maxlen );
167 unsigned long loadSmallBlock(
unsigned long block,
unsigned char* buffer,
unsigned long maxlen );
169 StreamIO* streamIO(
const std::string& name );
173 StorageIO(
const StorageIO& );
174 StorageIO& operator=(
const StorageIO& );
183 std::string fullName;
187 StreamIO( StorageIO* io, DirEntry* entry );
189 unsigned long size();
190 void seek(
unsigned long pos );
191 unsigned long tell();
193 unsigned long read(
unsigned char* data,
unsigned long maxlen );
194 unsigned long read(
unsigned long pos,
unsigned char* data,
unsigned long maxlen );
198 std::vector<unsigned long> blocks;
201 StreamIO(
const StreamIO& );
202 StreamIO& operator=(
const StreamIO& );
208 unsigned char* cache_data;
209 unsigned long cache_size;
210 unsigned long cache_pos;
218static inline unsigned long readU16(
const unsigned char* ptr )
220 return ptr[0]+(ptr[1]<<8);
223static inline unsigned long readU32(
const unsigned char* ptr )
225 return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
228static inline void writeU16(
unsigned char* ptr,
unsigned long data )
230 ptr[0] = (
unsigned char)(data & 0xff);
231 ptr[1] = (
unsigned char)((data >> 8) & 0xff);
234static inline void writeU32(
unsigned char* ptr,
unsigned long data )
236 ptr[0] = (
unsigned char)(data & 0xff);
237 ptr[1] = (
unsigned char)((data >> 8) & 0xff);
238 ptr[2] = (
unsigned char)((data >> 16) & 0xff);
239 ptr[3] = (
unsigned char)((data >> 24) & 0xff);
242static const unsigned char pole_magic[] =
243 { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
259 for(
unsigned i = 0; i < 8; i++ )
260 id[i] = pole_magic[i];
261 for(
unsigned i=0; i<109; i++ )
262 bb_blocks[i] = AllocTable::Avail;
267 if( threshold != 4096 )
return false;
268 if( num_bat == 0 )
return false;
269 if( (num_bat > 109) && (num_bat > (num_mbat * 127) + 109))
return false;
270 if( (num_bat < 109) && (num_mbat != 0) )
return false;
271 if( s_shift > b_shift )
return false;
272 if( b_shift <= 6 )
return false;
273 if( b_shift >=31 )
return false;
278void Header::load(
const unsigned char* buffer )
280 b_shift = readU16( buffer + 0x1e );
281 s_shift = readU16( buffer + 0x20 );
282 num_bat = readU32( buffer + 0x2c );
283 dirent_start = readU32( buffer + 0x30 );
284 threshold = readU32( buffer + 0x38 );
285 sbat_start = readU32( buffer + 0x3c );
286 num_sbat = readU32( buffer + 0x40 );
287 mbat_start = readU32( buffer + 0x44 );
288 num_mbat = readU32( buffer + 0x48 );
290 for(
unsigned i = 0; i < 8; i++ )
292 for(
unsigned i=0; i<109; i++ )
293 bb_blocks[i] = readU32( buffer + 0x4C+i*4 );
296void Header::save(
unsigned char* buffer )
298 memset( buffer, 0, 0x4c );
299 memcpy( buffer, pole_magic, 8 );
300 writeU32( buffer + 8, 0 );
301 writeU32( buffer + 12, 0 );
302 writeU32( buffer + 16, 0 );
303 writeU16( buffer + 24, 0x003e );
304 writeU16( buffer + 26, 3 );
305 writeU16( buffer + 28, 0xfffe );
306 writeU16( buffer + 0x1e, b_shift );
307 writeU16( buffer + 0x20, s_shift );
308 writeU32( buffer + 0x2c, num_bat );
309 writeU32( buffer + 0x30, dirent_start );
310 writeU32( buffer + 0x38, threshold );
311 writeU32( buffer + 0x3c, sbat_start );
312 writeU32( buffer + 0x40, num_sbat );
313 writeU32( buffer + 0x44, mbat_start );
314 writeU32( buffer + 0x48, num_mbat );
316 for(
unsigned i=0; i<109; i++ )
317 writeU32( buffer + 0x4C+i*4, bb_blocks[i] );
322 std::cout << std::endl;
323 std::cout <<
"b_shift " << b_shift << std::endl;
324 std::cout <<
"s_shift " << s_shift << std::endl;
325 std::cout <<
"num_bat " << num_bat << std::endl;
326 std::cout <<
"dirent_start " << dirent_start << std::endl;
327 std::cout <<
"threshold " << threshold << std::endl;
328 std::cout <<
"sbat_start " << sbat_start << std::endl;
329 std::cout <<
"num_sbat " << num_sbat << std::endl;
330 std::cout <<
"mbat_start " << mbat_start << std::endl;
331 std::cout <<
"num_mbat " << num_mbat << std::endl;
333 unsigned s = (num_bat<=109) ? num_bat : 109;
334 std::cout <<
"bat blocks: ";
335 for(
unsigned i = 0; i < s; i++ )
336 std::cout << bb_blocks[i] <<
" ";
337 std::cout << std::endl;
342const unsigned AllocTable::Avail = 0xffffffff;
343const unsigned AllocTable::Eof = 0xfffffffe;
344const unsigned AllocTable::Bat = 0xfffffffd;
345const unsigned AllocTable::MetaBat = 0xfffffffc;
347AllocTable::AllocTable()
354unsigned long AllocTable::count()
359void AllocTable::resize(
unsigned long newsize )
361 unsigned oldsize = data.size();
362 data.resize( newsize );
363 if( newsize > oldsize )
364 for(
unsigned i = oldsize; i<newsize; i++ )
369void AllocTable::preserve(
unsigned long n )
371 std::vector<unsigned long> pre;
372 for(
unsigned i=0; i < n; i++ )
373 pre.push_back( unused() );
376unsigned long AllocTable::operator[](
unsigned long index )
378 unsigned long result;
379 result = data[index];
383void AllocTable::set(
unsigned long index,
unsigned long value )
385 if( index >= count() ) resize( index + 1);
386 data[ index ] = value;
389void AllocTable::setChain( std::vector<unsigned long> chain )
393 for(
unsigned i=0; i<chain.size()-1; i++ )
394 set( chain[i], chain[i+1] );
395 set( chain[ chain.size()-1 ], AllocTable::Eof );
400std::vector<unsigned long> AllocTable::follow(
unsigned long start )
402 std::vector<unsigned long> chain;
404 if( start >= count() )
return chain;
406 unsigned long p = start;
409 if( p == (
unsigned long)Eof )
break;
410 if( p == (
unsigned long)Bat )
break;
411 if( p == (
unsigned long)MetaBat )
break;
412 if( p >= count() )
break;
413 chain.push_back( p );
414 if( data[p] >= count() )
break;
421unsigned AllocTable::unused()
424 for(
unsigned i = 0; i < data.size(); i++ )
425 if( data[i] == Avail )
429 unsigned block = data.size();
430 resize( data.size()+10 );
434void AllocTable::load(
const unsigned char* buffer,
unsigned len )
437 for(
unsigned i = 0; i < count(); i++ )
438 set( i, readU32( buffer + i*4 ) );
442unsigned AllocTable::size()
447void AllocTable::save(
unsigned char* buffer )
449 for(
unsigned i = 0; i < count(); i++ )
450 writeU32( buffer + i*4, data[i] );
453void AllocTable::debug()
455 std::cout <<
"block size " << data.size() << std::endl;
456 for(
unsigned i=0; i< data.size(); i++ )
458 if( data[i] == Avail )
continue;
459 std::cout << i <<
": ";
460 if( data[i] == Eof ) std::cout <<
"[eof]";
461 else if( data[i] == Bat ) std::cout <<
"[bat]";
462 else if( data[i] == MetaBat ) std::cout <<
"[metabat]";
463 else std::cout << data[i];
464 std::cout << std::endl;
470const unsigned DirTree::End = 0xffffffff;
481 entries[0].valid =
true;
482 entries[0].name =
"Root Entry";
483 entries[0].dir =
true;
485 entries[0].start = End;
486 entries[0].prev = End;
487 entries[0].next = End;
488 entries[0].child = End;
491unsigned DirTree::entryCount()
493 return entries.size();
496DirEntry* DirTree::entry(
unsigned index )
498 if( index >= entryCount() )
return (DirEntry*) 0;
499 return &entries[ index ];
502int DirTree::indexOf( DirEntry* e )
504 for(
unsigned i = 0; i < entryCount(); i++ )
505 if( entry( i ) == e )
return i;
510int DirTree::parent(
unsigned index )
514 for(
unsigned j=0; j<entryCount(); j++ )
516 std::vector<unsigned> chi = children( j );
517 for(
unsigned i=0; i<chi.size();i++ )
518 if( chi[i] == index )
525std::string DirTree::fullName(
unsigned index )
528 if( index == 0 )
return "/";
530 std::string result = entry( index )->name;
531 result.insert( 0,
"/" );
532 int p = parent( index );
533 DirEntry * _entry = 0;
537 if (_entry->dir && _entry->valid)
539 result.insert( 0, _entry->name);
540 result.insert( 0,
"/" );
544 if( index <= 0 )
break;
552DirEntry* DirTree::entry(
const std::string& name,
bool create )
554 if( !name.length() )
return (DirEntry*)0;
557 if( name ==
"/" )
return entry( 0 );
561 std::list<std::string> names;
562 std::string::size_type start = 0, end = 0;
563 if( name[0] ==
'/' ) start++;
564 while( start < name.length() )
566 end = name.find_first_of(
'/', start );
567 if( end == std::string::npos ) end = name.length();
568 names.push_back( name.substr( start, end-start ) );
576 std::list<std::string>::iterator it;
578 for( it = names.begin(); it != names.end(); ++it )
581 std::vector<unsigned> chi = children( index );
583 for(
unsigned i = 0; i < chi.size(); i++ )
585 DirEntry* ce = entry( chi[i] );
587 if( ce->valid && ( ce->name.length()>1 ) )
588 if( ce->name == *it )
593 if( child > 0 ) index = child;
597 if( !create )
return (DirEntry*)0;
600 unsigned parent = index;
601 entries.push_back( DirEntry() );
602 index = entryCount()-1;
603 DirEntry* e = entry( index );
611 e->next = entry(parent)->child;
612 entry(parent)->child = index;
616 return entry( index );
620void dirtree_find_siblings( DirTree* dirtree, std::vector<unsigned>& result,
623 DirEntry* e = dirtree->entry( index );
625 if( !e->valid )
return;
628 for(
unsigned i = 0; i < result.size(); i++ )
629 if( result[i] == index )
return;
632 result.push_back( index );
635 unsigned prev = e->prev;
636 if( ( prev > 0 ) && ( prev < dirtree->entryCount() ) )
638 for(
unsigned i = 0; i < result.size(); i++ )
639 if( result[i] == prev ) prev = 0;
640 if( prev ) dirtree_find_siblings( dirtree, result, prev );
644 unsigned next = e->next;
645 if( ( next > 0 ) && ( next < dirtree->entryCount() ) )
647 for(
unsigned i = 0; i < result.size(); i++ )
648 if( result[i] == next ) next = 0;
649 if( next ) dirtree_find_siblings( dirtree, result, next );
653std::vector<unsigned> DirTree::children(
unsigned index )
655 std::vector<unsigned> result;
657 DirEntry* e = entry( index );
658 if( e )
if( e->valid && e->child < entryCount() )
659 dirtree_find_siblings(
this, result, e->child );
664void DirTree::load(
unsigned char* buffer,
unsigned size )
668 for(
unsigned i = 0; i < size/128; i++ )
670 unsigned p = i * 128;
673 unsigned prefix = 32;
677 int name_len = readU16( buffer + 0x40+p );
678 if( name_len > 64 ) name_len = 64;
679 for(
int j=0; ( buffer[j+p]) && (j<name_len); j+= 2 )
680 name.append( 1, buffer[j+p] );
690 unsigned type = buffer[ 0x42 + p];
695 e.start = readU32( buffer + 0x74+p );
696 e.size = readU32( buffer + 0x78+p );
697 e.prev = readU32( buffer + 0x44+p );
698 e.next = readU32( buffer + 0x48+p );
699 e.child = readU32( buffer + 0x4C+p );
703 if( (type != 2) && (type != 1 ) && (type != 5 ) ) e.valid =
false;
704 if( name_len < 1 ) e.valid =
false;
706 entries.push_back( e );
711unsigned DirTree::size()
713 return entryCount() * 128;
716void DirTree::save(
unsigned char* buffer )
718 memset( buffer, 0, size() );
721 DirEntry* root = entry( 0 );
722 std::string name =
"Root Entry";
723 for(
unsigned j = 0; j < name.length(); j++ )
724 buffer[ j*2 ] = name[j];
725 writeU16( buffer + 0x40, name.length()*2 + 2 );
726 writeU32( buffer + 0x74, 0xffffffff );
727 writeU32( buffer + 0x78, 0 );
728 writeU32( buffer + 0x44, 0xffffffff );
729 writeU32( buffer + 0x48, 0xffffffff );
730 writeU32( buffer + 0x4c, root->child );
734 for(
unsigned i = 1; i < entryCount(); i++ )
736 DirEntry* e = entry( i );
740 e->start = 0xffffffff;
745 std::string name = e->name;
746 if( name.length() > 32 )
747 name.erase( 32, name.length() );
750 for(
unsigned j = 0; j < name.length(); j++ )
751 buffer[ i*128 + j*2 ] = name[j];
753 writeU16( buffer + i*128 + 0x40, name.length()*2 + 2 );
754 writeU32( buffer + i*128 + 0x74, e->start );
755 writeU32( buffer + i*128 + 0x78, e->size );
756 writeU32( buffer + i*128 + 0x44, e->prev );
757 writeU32( buffer + i*128 + 0x48, e->next );
758 writeU32( buffer + i*128 + 0x4c, e->child );
759 buffer[ i*128 + 0x42 ] = e->dir ? 1 : 2;
760 buffer[ i*128 + 0x43 ] = 1;
766 for(
unsigned i = 0; i < entryCount(); i++ )
768 DirEntry* e = entry( i );
770 std::cout << i <<
": ";
771 if( !e->valid ) std::cout <<
"INVALID ";
772 std::cout << e->name <<
" ";
773 if( e->dir ) std::cout <<
"(Dir) ";
774 else std::cout <<
"(File) ";
775 std::cout << e->size <<
" ";
776 std::cout <<
"s:" << e->start <<
" ";
778 if( e->child == End ) std::cout <<
"-";
else std::cout << e->child;
780 if( e->prev == End ) std::cout <<
"-";
else std::cout << e->prev;
782 if( e->next == End ) std::cout <<
"-";
else std::cout << e->next;
784 std::cout << std::endl;
790StorageIO::StorageIO( Storage* st,
const char* fname )
794 result = Storage::Ok;
797 header =
new Header();
798 dirtree =
new DirTree();
799 bbat =
new AllocTable();
800 sbat =
new AllocTable();
806 bbat->blockSize = 1 << header->b_shift;
807 sbat->blockSize = 1 << header->s_shift;
810StorageIO::~StorageIO()
812 if( opened ) close();
814 delete [] lastBlockData;
821bool StorageIO::open()
824 if( opened ) close();
828 return result == Storage::Ok;
831void StorageIO::load()
833 unsigned char* buffer = 0;
834 unsigned long buflen = 0;
835 std::vector<unsigned long> blocks;
838 result = Storage::OpenFailed;
839 file.open( filename.c_str(), std::ios::binary | std::ios::in );
840 if( !file.good() )
return;
843 file.seekg( 0, std::ios::end );
844 filesize = file.tellg();
847 buffer =
new unsigned char[512];
849 file.read( (
char*)buffer, 512 );
850 header->load( buffer );
854 result = Storage::NotOLE;
855 for(
unsigned i=0; i<8; i++ )
856 if( header->id[i] != pole_magic[i] )
860 result = Storage::BadOLE;
861 if( !header->valid() )
return;
862 if( header->threshold != 4096 )
return;
865 bbat->blockSize = 1 << header->b_shift;
866 sbat->blockSize = 1 << header->s_shift;
871 blocks.resize( header->num_bat );
872 for(
unsigned i = 0; i < 109; i++ )
873 if( i >= header->num_bat )
break;
874 else blocks[i] = header->bb_blocks[i];
875 if( (header->num_bat > 109) && (header->num_mbat > 0) )
877 unsigned char* buffer2 =
new unsigned char[ bbat->blockSize ];
879 unsigned mblock = header->mbat_start;
880 for(
unsigned r = 0; r < header->num_mbat; r++ )
882 loadBigBlock( mblock, buffer2, bbat->blockSize );
883 for(
unsigned s=0; s < bbat->blockSize-4; s+=4 )
885 if( k >= header->num_bat )
break;
886 else blocks[k++] = readU32( buffer2 + s );
888 mblock = readU32( buffer2 + bbat->blockSize-4 );
894 buflen = blocks.size()*bbat->blockSize;
897 buffer =
new unsigned char[ buflen ];
898 loadBigBlocks( blocks, buffer, buflen );
899 bbat->load( buffer, buflen );
905 blocks = bbat->follow( header->sbat_start );
906 buflen = blocks.size()*bbat->blockSize;
909 buffer =
new unsigned char[ buflen ];
910 loadBigBlocks( blocks, buffer, buflen );
911 sbat->load( buffer, buflen );
917 blocks = bbat->follow( header->dirent_start );
918 buflen = blocks.size()*bbat->blockSize;
919 buffer =
new unsigned char[ buflen ];
920 loadBigBlocks( blocks, buffer, buflen );
921 dirtree->load( buffer, buflen );
922 unsigned sb_start = readU32( buffer + 0x74 );
926 sb_blocks = bbat->follow( sb_start );
937 result = Storage::Ok;
941void StorageIO::create()
945 file.open( filename.c_str(), std::ios::out|std::ios::binary );
948 std::cerr <<
"Can't create " << filename << std::endl;
949 result = Storage::OpenFailed;
955 result = Storage::Ok;
958void StorageIO::flush()
967void StorageIO::close()
969 if( !opened )
return;
974 std::list<Stream*>::iterator it;
975 for( it = streams.begin(); it != streams.end(); ++it )
979StreamIO* StorageIO::streamIO(
const std::string& name )
982 if( !name.length() )
return (StreamIO*)0;
985 DirEntry* entry = dirtree->entry( name );
987 if( !entry )
return (StreamIO*)0;
989 if( entry->dir )
return (StreamIO*)0;
991 StreamIO* result =
new StreamIO(
this, entry );
992 result->fullName = name;
997unsigned long StorageIO::loadBigBlocks( std::vector<unsigned long> blocks,
998 unsigned char* data,
unsigned long maxlen )
1001 if( !data )
return 0;
1002 if( !file.good() )
return 0;
1003 if( blocks.size() < 1 )
return 0;
1004 if( maxlen == 0 )
return 0;
1007 unsigned long bytes = 0;
1008 for(
unsigned long i=0; (i < blocks.size() ) && ( bytes<maxlen ); i++ )
1010 unsigned long block = blocks[i];
1011 unsigned long pos = bbat->blockSize * ( block+1 );
1012 unsigned long p = (bbat->blockSize < maxlen-bytes) ? bbat->blockSize : maxlen-bytes;
1013 if( pos + p > filesize ) p = filesize - pos;
1015 file.read( (
char*)data + bytes, p );
1023#define POLE_CACHE_BLOCK
1025unsigned long StorageIO::loadBigBlock(
unsigned long block,
1026 unsigned char* data,
unsigned long maxlen )
1029 if( !data )
return 0;
1030 if( !file.good() )
return 0;
1032#ifdef POLE_CACHE_BLOCK
1035 if( block == lastBlockIndex )
1036 if( lastBlockData)
if( maxlen <= bbat->blockSize )
1038 memcpy( data, lastBlockData, maxlen );
1044 std::vector<unsigned long> blocks;
1048 unsigned long result = loadBigBlocks( blocks, data, maxlen );
1050#ifdef POLE_CACHE_BLOCK
1052 if(maxlen == bbat->blockSize )
1054 if( !lastBlockData )
1055 lastBlockData =
new unsigned char[bbat->blockSize];
1056 memcpy(lastBlockData, data, bbat->blockSize);
1057 lastBlockIndex = block;
1065unsigned long StorageIO::loadSmallBlocks( std::vector<unsigned long> blocks,
1066 unsigned char* data,
unsigned long maxlen )
1069 if( !data )
return 0;
1070 if( !file.good() )
return 0;
1071 if( blocks.size() < 1 )
return 0;
1072 if( maxlen == 0 )
return 0;
1075 unsigned char* buf =
new unsigned char[ bbat->blockSize ];
1078 unsigned long bytes = 0;
1079 for(
unsigned long i=0; ( i<blocks.size() ) && ( bytes<maxlen ); i++ )
1081 unsigned long block = blocks[i];
1084 unsigned long pos = block * sbat->blockSize;
1085 unsigned long bbindex = pos / bbat->blockSize;
1086 if( bbindex >= sb_blocks.size() )
break;
1088 loadBigBlock( sb_blocks[ bbindex ], buf, bbat->blockSize );
1091 unsigned offset = pos % bbat->blockSize;
1092 unsigned long p = (maxlen-bytes < bbat->blockSize-offset ) ? maxlen-bytes : bbat->blockSize-offset;
1093 p = (sbat->blockSize<p ) ? sbat->blockSize : p;
1094 memcpy( data + bytes, buf + offset, p );
1103unsigned long StorageIO::loadSmallBlock(
unsigned long block,
1104 unsigned char* data,
unsigned long maxlen )
1107 if( !data )
return 0;
1108 if( !file.good() )
return 0;
1111 std::vector<unsigned long> blocks;
1113 blocks.assign( 1, block );
1115 return loadSmallBlocks( blocks, data, maxlen );
1120StreamIO::StreamIO( StorageIO* s, DirEntry* e)
1129 if( entry->size >= io->header->threshold )
1130 blocks = io->bbat->follow( entry->start );
1132 blocks = io->sbat->follow( entry->start );
1137 cache_data =
new unsigned char[cache_size];
1142StreamIO::~StreamIO()
1144 delete[] cache_data;
1147void StreamIO::seek(
unsigned long pos )
1152unsigned long StreamIO::tell()
1157int StreamIO::getch()
1160 if( m_pos > entry->size )
return -1;
1163 if( !cache_size || ( m_pos < cache_pos ) ||
1164 ( m_pos >= cache_pos + cache_size ) )
1168 if( !cache_size )
return -1;
1170 int data = cache_data[m_pos - cache_pos];
1176unsigned long StreamIO::read(
unsigned long pos,
unsigned char* data,
unsigned long maxlen )
1179 if( !data )
return 0;
1180 if( maxlen == 0 )
return 0;
1182 unsigned long totalbytes = 0;
1184 if ( entry->size < io->header->threshold )
1187 unsigned long index = pos / io->sbat->blockSize;
1189 if( index >= blocks.size() )
return 0;
1191 unsigned char* buf =
new unsigned char[ io->sbat->blockSize ];
1192 unsigned long offset = pos % io->sbat->blockSize;
1193 while( totalbytes < maxlen )
1195 if( index >= blocks.size() )
break;
1196 io->loadSmallBlock( blocks[index], buf, io->bbat->blockSize );
1197 unsigned long count = io->sbat->blockSize - offset;
1198 if( count > maxlen-totalbytes ) count = maxlen-totalbytes;
1199 memcpy( data+totalbytes, buf + offset, count );
1200 totalbytes += count;
1210 unsigned long index = pos / io->bbat->blockSize;
1213 if( index >= blocks.size() )
return 0;
1215 unsigned char* buf =
new unsigned char[ io->bbat->blockSize ];
1216 unsigned long offset = pos % io->bbat->blockSize;
1217 while( totalbytes < maxlen )
1219 if( index >= blocks.size() )
break;
1220 io->loadBigBlock( blocks[index], buf, io->bbat->blockSize );
1221 unsigned long count = io->bbat->blockSize - offset;
1222 if( count > maxlen-totalbytes ) count = maxlen-totalbytes;
1223 memcpy( data+totalbytes, buf + offset, count );
1224 totalbytes += count;
1235unsigned long StreamIO::read(
unsigned char* data,
unsigned long maxlen )
1237 unsigned long bytes = read( tell(), data, maxlen );
1242void StreamIO::updateCache()
1245 if( !cache_data )
return;
1247 cache_pos = m_pos - ( m_pos % cache_size );
1248 unsigned long bytes = cache_size;
1249 if( cache_pos + bytes > entry->size ) bytes = entry->size - cache_pos;
1250 cache_size = read( cache_pos, cache_data, bytes );
1256Storage::Storage(
const char* filename )
1258 io =
new StorageIO(
this, filename );
1266int Storage::result()
1276void Storage::close()
1281std::list<std::string> Storage::entries(
const std::string& path )
1283 std::list<std::string> result;
1284 DirTree* dt = io->dirtree;
1285 DirEntry* e = dt->entry( path,
false );
1288 unsigned parent = dt->indexOf( e );
1289 std::vector<unsigned> children = dt->children( parent );
1290 for(
unsigned i = 0; i < children.size(); i++ )
1291 result.push_back( dt->entry( children[i] )->name );
1297bool Storage::isDirectory(
const std::string& name )
1299 DirEntry* e = io->dirtree->entry( name,
false );
1300 return e ? e->dir :
false;
1305Stream::Stream( Storage* storage,
const std::string& name )
1307 io = storage->io->streamIO( name );
1316std::string Stream::fullName()
1318 return io ? io->fullName : std::string();
1321unsigned long Stream::tell()
1323 return io ? io->tell() : 0;
1326void Stream::seek(
unsigned long newpos )
1328 if( io ) io->seek( newpos );
1331unsigned long Stream::size()
1333 return io ? io->entry->size : 0;
1338 return io ? io->getch() : 0;
1341unsigned long Stream::read(
unsigned char* data,
unsigned long maxlen )
1343 return io ? io->read( data, maxlen ) : 0;
1348 return io ? io->eof :
false;
1353 return io ? io->fail :
true;