00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <fstream>
00021 #include <string>
00022 #include <list>
00023 #include <iostream>
00024 #include <vector>
00025
00026 #include "pole.h"
00027
00028 namespace POLE
00029 {
00030
00031 class Entry
00032 {
00033 public:
00034 Entry* parent;
00035 std::string name;
00036 unsigned long size;
00037 unsigned start;
00038 bool dir;
00039 std::vector<Entry*> children;
00040 Entry();
00041 ~Entry();
00042 private:
00043 Entry( const Entry& );
00044 Entry& operator=( const Entry& );
00045 };
00046
00047 class AllocTable
00048 {
00049 public:
00050
00051 AllocTable();
00052
00053 ~AllocTable();
00054
00055 bool dirty;
00056
00057 void clear();
00058
00059 unsigned long size();
00060
00061 void resize( unsigned long newsize );
00062
00063 void set( unsigned long index, unsigned long val );
00064
00065 std::vector<unsigned long> follow( unsigned long start );
00066
00067 unsigned long operator[](unsigned long index );
00068
00069 private:
00070
00071 std::vector<unsigned long> data;
00072
00073 AllocTable( const AllocTable& );
00074
00075 AllocTable& operator=( const AllocTable& );
00076 };
00077
00078 class StorageIO
00079 {
00080 public:
00081
00083 int result;
00084
00086 Storage* doc;
00087
00089 std::string filename;
00090
00092 int mode;
00093
00095 std::fstream file;
00096
00098 unsigned long filesize;
00099
00101 unsigned char header[512];
00102
00104 unsigned char magic[8];
00105
00107 unsigned threshold;
00108
00110 unsigned bb_size;
00111
00113 unsigned sb_size;
00114
00116 AllocTable bb;
00117
00119 AllocTable sb;
00120
00122 unsigned sbat_start;
00123
00125 std::vector<unsigned long> sb_blocks;
00126
00128 unsigned mbat_start;
00129
00131 unsigned dirent_start;
00132
00134 Entry* root;
00135
00137 Entry* current_dir;
00138
00140 StorageIO( Storage* storage, const char* fileName, int mode );
00141
00143 ~StorageIO();
00144
00145 void flush();
00146
00147 unsigned long loadBigBlocks( std::vector<unsigned long> blocks, unsigned char* buffer, unsigned long maxlen );
00148
00149 unsigned long loadBigBlock( unsigned long block, unsigned char* buffer, unsigned long maxlen );
00150
00151 unsigned long loadSmallBlocks( std::vector<unsigned long> blocks, unsigned char* buffer, unsigned long maxlen );
00152
00153 unsigned long loadSmallBlock( unsigned long block, unsigned char* buffer, unsigned long maxlen );
00154
00156 Entry* buildTree( Entry* parent, int index, const unsigned char* dirent );
00157
00158 std::string fullName( Entry* e );
00159
00161 Entry* entry( const std::string& name );
00162
00163
00164 private:
00165
00166 void load();
00167
00168 void create();
00169
00170
00171 StorageIO( const StorageIO& );
00172 StorageIO& operator=( const StorageIO& );
00173
00174 };
00175
00176 class StreamIO
00177 {
00178 public:
00179
00180 StreamIO( StorageIO* io, Entry* entry );
00181
00182 ~StreamIO();
00183
00184 unsigned long size();
00185
00186 void seek( unsigned long pos );
00187
00188 unsigned long tell();
00189
00190 int getch();
00191
00192 unsigned long read( unsigned char* data, unsigned long maxlen );
00193
00194 unsigned long read( unsigned long pos, unsigned char* data, unsigned long maxlen );
00195
00196 StorageIO* io;
00197
00198 Entry* entry;
00199
00200
00201 private:
00202
00203 std::vector<unsigned long> blocks;
00204
00205
00206 StreamIO( const StreamIO& );
00207 StreamIO& operator=( const StreamIO& );
00208
00209
00210 unsigned long m_pos;
00211
00212
00213 unsigned char* cache_data;
00214 unsigned long cache_size;
00215 unsigned long cache_pos;
00216 void updateCache();
00217
00218 };
00219
00220 };
00221
00222 using namespace POLE;
00223
00224 static inline unsigned long readU16( const unsigned char* ptr )
00225 {
00226 return ptr[0]+(ptr[1]<<8);
00227 }
00228
00229 static inline unsigned long readU32( const unsigned char* ptr )
00230 {
00231 return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
00232 }
00233
00234 static inline void writeU16( unsigned char* ptr, unsigned long data )
00235 {
00236 ptr[0] = data & 0xff;
00237 ptr[1] = (data >> 8) & 0xff;
00238 }
00239
00240 static inline void writeU32( unsigned char* ptr, unsigned long data )
00241 {
00242 ptr[0] = data & 0xff;
00243 ptr[1] = (data >> 8) & 0xff;
00244 ptr[2] = (data >> 16) & 0xff;
00245 ptr[3] = (data >> 24) & 0xff;
00246 }
00247
00248 static const unsigned char pole_magic[] =
00249 { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
00250
00251 Entry::Entry()
00252 {
00253 name = "Unnamed";
00254 size = 0;
00255 dir = false;
00256 }
00257
00258 Entry::~Entry()
00259 {
00260 for( unsigned i=0; i<children.size(); i++ )
00261 {
00262 Entry* entry = children[ i ];
00263 delete entry;
00264 }
00265 }
00266
00267 AllocTable::AllocTable()
00268 {
00269 dirty = false;
00270 }
00271
00272 AllocTable::~AllocTable()
00273 {
00274 }
00275
00276 unsigned long AllocTable::size()
00277 {
00278 return data.size();
00279 }
00280
00281 void AllocTable::resize( unsigned long newsize )
00282 {
00283 data.resize( newsize );
00284 }
00285
00286 unsigned long AllocTable::operator[]( unsigned long index )
00287 {
00288 unsigned long result;
00289 result = data[index];
00290 return result;
00291 }
00292
00293 void AllocTable::set( unsigned long index, unsigned long value )
00294 {
00295 if( index >= size() ) resize( index + 1);
00296 data[ index ] = value;
00297 }
00298
00299 std::vector<unsigned long> AllocTable::follow( unsigned long start )
00300 {
00301 std::vector<unsigned long> chain;
00302
00303 if( start >= size() ) return chain;
00304
00305 unsigned long p = start;
00306 while( p < size() )
00307 {
00308 if( p >= (unsigned long)0xfffe ) break;
00309 if( p >= size() ) break;
00310 chain.push_back( p );
00311 if( data[p] >= size() ) break;
00312 p = data[ p ];
00313 }
00314
00315 return chain;
00316 }
00317
00318
00319
00320 StorageIO::StorageIO( Storage* storage, const char* fname, int m ):
00321 doc( storage ), filename( fname), mode( m )
00322 {
00323
00324 result = Storage::Ok;
00325 root = (Entry*) 0L;
00326 current_dir = (Entry*) 0L;
00327 bb_size = 512;
00328 sb_size = 64;
00329 threshold = 4096;
00330
00331
00332 int om = std::ios::in;
00333 if( mode == Storage::WriteOnly ) om = std::ios::out;
00334 if( mode == Storage::ReadWrite) om = std::ios::app;
00335 om |= std::ios::binary;
00336
00337 file.open( filename.c_str(), std::ios::binary | std::ios::in );
00338
00339
00340 if( !file.good() )
00341 {
00342 std::cerr << "Can't open " << filename << "\n\n";
00343 result = Storage::OpenFailed;
00344 return;
00345 }
00346
00347
00348 result = Storage::Ok;
00349
00350 if( mode == Storage::WriteOnly ) create();
00351 else load();
00352
00353 }
00354
00355 StorageIO::~StorageIO()
00356 {
00357 filename = std::string();
00358 flush();
00359 file.close();
00360 }
00361
00362 void StorageIO::load()
00363 {
00364 unsigned bb_shift;
00365 unsigned sb_shift;
00366 unsigned num_bat;
00367 unsigned num_sbat;
00368 unsigned num_mbat;
00369
00370
00371 file.seekg( 0, std::ios::end );
00372 filesize = file.tellg();
00373
00374
00375 file.seekg( 0 );
00376 file.read( (char*)header, sizeof( header ) );
00377 if( file.gcount() != sizeof( header ) )
00378 {
00379 result = Storage::NotOLE;
00380 return;
00381 }
00382
00383
00384 for( unsigned i=0; i<8; i++ )
00385 {
00386 magic[i] = header[i];
00387 if( magic[i] != pole_magic[i] )
00388 {
00389 result = Storage::NotOLE;
00390 return;
00391 }
00392 }
00393
00394
00395 bb_shift = readU16( header + 0x1e );
00396 sb_shift = readU16( header + 0x20 );
00397 num_bat = readU32( header + 0x2c );
00398 dirent_start = readU32( header + 0x30 );
00399 threshold = readU32( header + 0x38 );
00400 sbat_start = readU32( header + 0x3c );
00401 num_sbat = readU32( header + 0x40 );
00402 mbat_start = readU32( header + 0x44 );
00403 num_mbat = readU32( header + 0x48 );
00404
00405
00406 if( ( threshold != 4096 ) || ( num_bat == 0 ) ||
00407 ( sb_shift > bb_shift ) || ( bb_shift <= 6 ) || ( bb_shift >=31 ) )
00408 {
00409 result = Storage::BadOLE;
00410 return;
00411 }
00412
00413
00414 bb_size = 1 << bb_shift;
00415 sb_size = 1 << sb_shift;
00416
00417 std::vector<unsigned long> chain;
00418 unsigned char buffer[bb_size];
00419
00420
00421 std::vector<unsigned long> metabat( num_mbat * bb_size / 4 );
00422 unsigned q = 0;
00423 for( unsigned r=0; r<num_mbat; r++ )
00424 {
00425 unsigned char metabuf[ bb_size ];
00426 loadBigBlock( mbat_start+r, metabuf, sizeof( metabuf ) );
00427 for( unsigned s=0; s< bb_size/4; s++ )
00428 metabat[q++] = readU32( metabuf + s*4 );
00429 }
00430
00431
00432
00433 bb.resize( num_bat * bb_size / 4 );
00434 for( unsigned long i=0; i< num_bat; i++ )
00435 {
00436
00437
00438 unsigned long block = (i<109) ? readU32( header + 0x4C+i*4 ) : metabat[i-109];
00439
00440 loadBigBlock( block, buffer, bb_size );
00441
00442 for( unsigned m=0; m<bb_size/4; m++)
00443 bb.set( i*bb_size/4 + m, readU32( buffer + m*4 ) );
00444 }
00445
00446
00447
00448 chain = bb.follow( sbat_start );
00449
00450 for( unsigned long i=0; i < chain.size(); i++ )
00451 {
00452 unsigned long block = chain[i];
00453 loadBigBlock( block, buffer, bb_size );
00454 for( unsigned m=0; m<bb_size/4; m++ )
00455 sb.set( i*bb_size/4 + m, readU32( buffer + m*4 ) );
00456 }
00457
00458
00459 unsigned char* dirent;
00460 chain = bb.follow( dirent_start );
00461 unsigned bufsize = chain.size() * bb_size;
00462 dirent = new unsigned char[bufsize];
00463 loadBigBlocks( chain, dirent, bufsize );
00464 root = buildTree( (Entry*)0L, 0, dirent );
00465
00466
00467 sb_blocks = bb.follow( readU32( dirent + 0x74 ) );
00468
00469 delete [] dirent;
00470
00471
00472 current_dir = root;
00473
00474
00475 result = Storage::Ok;
00476 }
00477
00478
00479 void StorageIO::create()
00480 {
00481 unsigned bb_shift = 9;
00482 unsigned sb_shift = 6;
00483 bb_size = 1 << bb_shift;
00484 sb_size = 1 << sb_shift;
00485 threshold = 4096;
00486
00487
00488
00489 for( int i=0; i<8; i++ ) header[i] = pole_magic[i];
00490 writeU32( header + 8, 0 );
00491 writeU32( header + 12, 0 );
00492 writeU32( header + 16, 0 );
00493 writeU16( header + 24, 0x3B00 );
00494 writeU16( header + 26, 3 );
00495 writeU16( header + 28, 0xfffe );
00496 writeU16( header + 30, bb_shift );
00497 writeU16( header + 32, sb_shift );
00498 writeU16( header + 34, 0 );
00499 writeU32( header + 36, 0 );
00500 writeU32( header + 40, 0 );
00501 writeU32( header + 52, 0 );
00502 for( int j=0x4C; j<512; j++ ) header[j] = 0xff;
00503
00504
00505 result = Storage::Ok;
00506 }
00507
00508 void StorageIO::flush()
00509 {
00510 if( mode == Storage::ReadOnly ) return;
00511
00512
00513 writeU32( header + 0x30, dirent_start );
00514 writeU32( header + 0x38, threshold );
00515 writeU32( header + 0x3c, sbat_start );
00516 writeU32( header + 0x44, mbat_start );
00517
00518
00519
00520
00521
00522
00523 }
00524
00525 unsigned long StorageIO::loadBigBlocks( std::vector<unsigned long> blocks,
00526 unsigned char* data, unsigned long maxlen )
00527 {
00528
00529 if( !data ) return 0;
00530 if( !file.good() ) return 0;
00531 if( blocks.size() < 1 ) return 0;
00532 if( maxlen == 0 ) return 0;
00533
00534
00535 unsigned long bytes = 0;
00536 for( unsigned long i=0; (i < blocks.size() ) & ( bytes<maxlen ); i++ )
00537 {
00538 unsigned long block = blocks[i];
00539 if( block < 0 ) continue;
00540 unsigned long pos = bb_size * ( block+1 );
00541 unsigned long p = (bb_size < maxlen-bytes) ? bb_size : maxlen-bytes;
00542 if( pos + p > filesize ) p = filesize - pos;
00543 file.seekg( pos );
00544 file.read( (char*)data + bytes, p );
00545 bytes += p;
00546 }
00547
00548 return bytes;
00549 }
00550
00551 unsigned long StorageIO::loadBigBlock( unsigned long block,
00552 unsigned char* data, unsigned long maxlen )
00553 {
00554
00555 if( !data ) return 0;
00556 if( !file.good() ) return 0;
00557 if( block < 0 ) return 0;
00558
00559
00560 std::vector<unsigned long> blocks;
00561 blocks.resize( 1 );
00562 blocks[ 0 ] = block;
00563
00564 return loadBigBlocks( blocks, data, maxlen );
00565 }
00566
00567
00568 unsigned long StorageIO::loadSmallBlocks( std::vector<unsigned long> blocks,
00569 unsigned char* data, unsigned long maxlen )
00570 {
00571
00572 if( !data ) return 0;
00573 if( !file.good() ) return 0;
00574 if( blocks.size() < 1 ) return 0;
00575 if( maxlen == 0 ) return 0;
00576
00577
00578 unsigned char buf[ bb_size ];
00579
00580
00581 unsigned long bytes = 0;
00582 for( unsigned long i=0; ( i<blocks.size() ) & ( bytes<maxlen ); i++ )
00583 {
00584 unsigned long block = blocks[i];
00585 if( block < 0 ) continue;
00586
00587
00588 unsigned long pos = block * sb_size;
00589 unsigned long bbindex = pos / bb_size;
00590 if( bbindex >= sb_blocks.size() ) break;
00591
00592 loadBigBlock( sb_blocks[ bbindex ], buf, bb_size );
00593
00594
00595 unsigned offset = pos % bb_size;
00596 unsigned long p = (maxlen-bytes < bb_size-offset ) ? maxlen-bytes : bb_size-offset;
00597 p = (sb_size<p ) ? sb_size : p;
00598 memcpy( data + bytes, buf + offset, p );
00599 bytes += p;
00600 }
00601
00602 return bytes;
00603 }
00604
00605 unsigned long StorageIO::loadSmallBlock( unsigned long block,
00606 unsigned char* data, unsigned long maxlen )
00607 {
00608
00609 if( !data ) return 0;
00610 if( !file.good() ) return 0;
00611 if( block < 0 ) return 0;
00612
00613
00614 std::vector<unsigned long> blocks;
00615 blocks.resize( 1 );
00616 blocks.assign( 1, block );
00617
00618 return loadSmallBlocks( blocks, data, maxlen );
00619 }
00620
00621
00622 Entry* StorageIO::buildTree( Entry* parent, int index, const unsigned char* dirent )
00623 {
00624 Entry* entry = (Entry*) 0L;
00625
00626
00627 unsigned p = index * 128;
00628
00629
00630 unsigned prefix = 32;
00631
00632
00633 std::string name;
00634 int name_len = readU16( dirent + 64+p );
00635 for( int j=0; ( dirent[j+p]) && (j<name_len); j+= 2 )
00636 name.append( 1, dirent[j+p] );
00637
00638
00639 if( !name.length() ) return entry;
00640
00641
00642 if( dirent[p] < 32 ){ prefix = dirent[0]; name.erase( 0,1 ); }
00643
00644
00645
00646 unsigned type = dirent[ 0x42 + p];
00647 if( ( type == 2 ) || ( type == 1 ) || ( type == 5 ) ) entry = new Entry();
00648 if( entry ) entry->dir = ( ( type = 1 ) || ( type == 5 ) );
00649
00650
00651 if( !entry ) return entry;
00652
00653
00654 entry->name = name;
00655 entry->start = readU32( dirent + 0x74+p );
00656 entry->size = readU32( dirent + 0x78+p );
00657
00658
00659 entry->parent = parent;
00660 if( parent ) parent->children.push_back( entry );
00661
00662
00663 int prev = readU32( dirent + 0x44+p );
00664 if( prev >= 0 ) buildTree( parent, prev, dirent );
00665
00666
00667 int dir = readU32( dirent + 0x4C+p );
00668 if( entry->dir && (dir > 0 ))
00669 buildTree( entry, dir, dirent );
00670
00671
00672 int next = readU32( dirent + 0x48+p );
00673 if( next >= 0 ) buildTree( parent, next, dirent );
00674 return entry;
00675 }
00676
00677
00678 std::string StorageIO::fullName( Entry* e )
00679 {
00680 if( !e ) return (const char*) 0L;
00681
00682 std::string result;
00683
00684 while( e->parent )
00685 {
00686 result.insert( 0, e->name );
00687 result.insert( 0, "/" );
00688 e = e->parent;
00689 }
00690
00691
00692 if( !result.length() ) result = "/";
00693
00694 return result;
00695 }
00696
00697
00698 Entry* StorageIO::entry( const std::string& name )
00699 {
00700 Entry* entry = (Entry*) 0L;
00701
00702
00703 if( !root ) return (Entry*) 0L;
00704 if( !name.length() ) return (Entry*) 0L;
00705
00706
00707
00708 entry = (name[0] == '/' ) ? root : current_dir;
00709
00710
00711
00712 std::list<std::string> names;
00713 std::string::size_type start = 0, end = 0;
00714 while( start < name.length() )
00715 {
00716 end = name.find_first_of( '/', start );
00717 if( end == std::string::npos ) end = name.length();
00718 names.push_back( name.substr( start, end-start ) );
00719 start = end+1;
00720 }
00721
00722 std::list<std::string>::iterator it;
00723 for( it = names.begin(); it != names.end(); ++it )
00724 {
00725 std::string entryname = *it;
00726 Entry *child = (Entry*) 0L;
00727 if( entry->dir )
00728 for( unsigned j=0; j < entry->children.size(); j++ )
00729 if( entry->children[j]->name == entryname )
00730 child = entry->children[j];
00731 if( !child ) return (Entry*) 0L;
00732 entry = child;
00733 }
00734
00735 return entry;
00736 }
00737
00738
00739
00740 StreamIO::StreamIO( StorageIO* _io, Entry* _entry ):
00741 io( _io ), entry( _entry ), m_pos( 0 ),
00742 cache_data( 0 ), cache_size( 0 ), cache_pos( 0 )
00743 {
00744 blocks = ( entry->size >= io->threshold ) ? io->bb.follow( entry->start ) :
00745 io->sb.follow( entry->start );
00746
00747
00748 cache_size = 4096;
00749 cache_data = new unsigned char[cache_size];
00750 updateCache();
00751 }
00752
00753
00754 StreamIO::~StreamIO()
00755 {
00756 delete[] cache_data;
00757 }
00758
00759 void StreamIO::seek( unsigned long pos )
00760 {
00761 m_pos = pos;
00762 }
00763
00764 unsigned long StreamIO::tell()
00765 {
00766 return m_pos;
00767 }
00768
00769 int StreamIO::getch()
00770 {
00771
00772 if( m_pos > entry->size ) return -1;
00773
00774
00775 if( !cache_size || ( m_pos < cache_pos ) ||
00776 ( m_pos >= cache_pos + cache_size ) )
00777 updateCache();
00778
00779
00780 if( !cache_size ) return -1;
00781
00782 int data = cache_data[m_pos - cache_pos];
00783 m_pos++;
00784
00785 return data;
00786 }
00787
00788 unsigned long StreamIO::read( unsigned long pos, unsigned char* data, unsigned long maxlen )
00789 {
00790
00791 if( !data ) return 0;
00792 if( maxlen == 0 ) return 0;
00793
00794 unsigned long totalbytes = 0;
00795
00796 if ( entry->size < io->threshold )
00797 {
00798
00799 unsigned long index = pos / io->sb_size;
00800
00801 if( index >= blocks.size() ) return 0;
00802
00803 unsigned char buf[ io->sb_size ];
00804 unsigned long offset = pos % io->sb_size;
00805 while( totalbytes < maxlen )
00806 {
00807 if( index >= blocks.size() ) break;
00808 io->loadSmallBlock( blocks[index], buf, io->bb_size );
00809 unsigned long count = io->sb_size - offset;
00810 if( count > maxlen-totalbytes ) count = maxlen-totalbytes;
00811 memcpy( data+totalbytes, buf + offset, count );
00812 totalbytes += count;
00813 offset = 0;
00814 index++;
00815 }
00816
00817 }
00818 else
00819 {
00820
00821 unsigned long index = pos / io->bb_size;
00822
00823 if( index >= blocks.size() ) return 0;
00824
00825 unsigned char buf[ io->bb_size ];
00826 unsigned long offset = pos % io->bb_size;
00827 while( totalbytes < maxlen )
00828 {
00829 if( index >= blocks.size() ) break;
00830 io->loadBigBlock( blocks[index], buf, io->bb_size );
00831 unsigned long count = io->bb_size - offset;
00832 if( count > maxlen-totalbytes ) count = maxlen-totalbytes;
00833 memcpy( data+totalbytes, buf + offset, count );
00834 totalbytes += count;
00835 index++;
00836 offset = 0;
00837 }
00838
00839 }
00840
00841 return totalbytes;
00842 }
00843
00844 unsigned long StreamIO::read( unsigned char* data, unsigned long maxlen )
00845 {
00846 unsigned long bytes = read( tell(), data, maxlen );
00847 m_pos += bytes;
00848 return bytes;
00849 }
00850
00851 void StreamIO::updateCache()
00852 {
00853
00854 if( !cache_data ) return;
00855
00856 cache_pos = m_pos - ( m_pos % cache_size );
00857 unsigned long bytes = cache_size;
00858 if( cache_pos + bytes > entry->size ) bytes = entry->size - cache_pos;
00859 cache_size = read( cache_pos, cache_data, bytes );
00860 }
00861
00862
00863
00864
00865 Storage::Storage()
00866 {
00867 io = (StorageIO*) 0L;
00868 result = Storage::Ok;
00869 }
00870
00871 Storage::~Storage()
00872 {
00873 close();
00874 delete io;
00875 }
00876
00877 bool Storage::open( const char* fileName, int m )
00878 {
00879
00880 if( ( m != ReadOnly ) && ( m != WriteOnly ) && ( m != ReadWrite ) )
00881 {
00882 result = UnknownError;
00883 return false;
00884 }
00885
00886 io = new StorageIO( this, fileName, m );
00887
00888 result = io->result;
00889
00890 return result == Storage::Ok;
00891 }
00892
00893 void Storage::flush()
00894 {
00895 if( io ) io->flush();
00896 }
00897
00898 void Storage::close()
00899 {
00900 flush();
00901 }
00902
00903
00904 std::list<std::string> Storage::listDirectory()
00905 {
00906 std::list<std::string> entries;
00907
00908
00909 if( !io ) return entries;
00910 if( !io->current_dir ) return entries;
00911
00912
00913 if( !io->current_dir->dir ) return entries;
00914
00915
00916 for( unsigned i = 0; i<io->current_dir->children.size(); i++ )
00917 {
00918 Entry* e = io->current_dir->children[i];
00919 if( e ) entries.push_back( e->name );
00920 }
00921
00922 return entries;
00923 }
00924
00925
00926 bool Storage::enterDirectory( const std::string& directory )
00927 {
00928
00929 if( !io ) return false;
00930 if( !io->current_dir ) return false;
00931
00932
00933 for( unsigned i = 0; i<io->current_dir->children.size(); i++ )
00934 {
00935 Entry* e = io->current_dir->children[i];
00936 if( e ) if( e->name == directory )
00937 if ( e->dir )
00938 {
00939 io->current_dir = e;
00940 return true;
00941 }
00942 }
00943
00944 return false;
00945 }
00946
00947
00948 void Storage::leaveDirectory()
00949 {
00950
00951 if( !io ) return;
00952 if( !io->current_dir ) return;
00953
00954 Entry* parent = io->current_dir->parent;
00955 if( parent ) if( parent->dir )
00956 io->current_dir = parent;
00957 }
00958
00959
00960 std::string Storage::path()
00961 {
00962
00963 if( !io ) return std::string();
00964 if( !io->current_dir ) return std::string();
00965
00966 return io->fullName( io->current_dir );
00967 }
00968
00969 Stream* Storage::stream( const std::string& name )
00970 {
00971
00972 if( !name.length() ) return (Stream*) 0L;
00973 if( !io ) return (Stream*) 0L;
00974
00975
00976 std::string fullName = name;
00977 if( name[0] != '/' ) fullName.insert( 0, path() + "/" );
00978
00979
00980 Entry* entry = io->entry( name );
00981 if( !entry ) return (Stream*) 0L;
00982
00983 StreamIO* sio = new StreamIO( io, entry );
00984 Stream* s = new Stream( sio );
00985
00986 return s;
00987 }
00988
00989
00990
00991 Stream::Stream( StreamIO* _io ):
00992 io( _io )
00993 {
00994 }
00995
00996
00997 Stream::~Stream()
00998 {
00999 delete io;
01000 }
01001
01002 unsigned long Stream::tell()
01003 {
01004 return io ? io->tell() : 0;
01005 }
01006
01007 void Stream::seek( unsigned long newpos )
01008 {
01009 if( io ) io->seek( newpos );
01010 }
01011
01012 unsigned long Stream::size()
01013 {
01014 return io ? io->entry->size : 0;
01015 }
01016
01017 int Stream::getch()
01018 {
01019 return io ? io->getch() : -1;
01020 }
01021
01022 unsigned long Stream::read( unsigned char* data, unsigned long maxlen )
01023 {
01024 return io ? io->read( data, maxlen ) : 0;
01025 }
01026