BFIOFILE.CPP (40482B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/BFIOFILE.CPP 1 3/03/97 10:24a Joe_bostic $ */ 17 /*********************************************************************************************** 18 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Westwood Library * 22 * * 23 * File Name : RAMFILE.CPP * 24 * * 25 * Programmer : David R. Dettmer * 26 * * 27 * Start Date : November 10, 1995 * 28 * * 29 * Last Update : November 10, 1995 [DRD] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * BufferIOFileClass::BufferIOFileClass -- Filename based constructor for a file object. * 34 * BufferIOFileClass::BufferIOFileClass -- default constructor for a file object. * 35 * BufferIOFileClass::Cache -- Load part or all of a file data into RAM. * 36 * BufferIOFileClass::Close -- Perform a closure of the file. * 37 * BufferIOFileClass::Commit -- Writes the cache to the file if it has changed. * 38 * BufferIOFileClass::Free -- Frees the allocated buffer. * 39 * BufferIOFileClass::Is_Available -- Checks for existence of file cached or on disk. * 40 * BufferIOFileClass::Is_Open -- Determines if the file is open. * 41 * BufferIOFileClass::Open -- Assigns name and opens file in one operation. * 42 * BufferIOFileClass::Open -- Opens the file object with the rights specified. * 43 * BufferIOFileClass::Read -- Reads data from the file cache. * 44 * BufferIOFileClass::Seek -- Moves the current file pointer in the file. * 45 * BufferIOFileClass::Set_Name -- Checks for name changed for a cached file. * 46 * BufferIOFileClass::Size -- Determines size of file (in bytes). * 47 * BufferIOFileClass::Write -- Writes data to the file cache. * 48 * BufferIOFileClass::~BufferIOFileClass -- Destructor for the file object. * 49 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 50 51 52 #include "bfiofile.h" 53 #include <string.h> 54 55 56 /*********************************************************************************************** 57 * BufferIOFileClass::BufferIOFileClass -- Filename based constructor for a file object. * 58 * * 59 * This constructor is called when a file object is created with a supplied filename, but * 60 * not opened at the same time. In this case, an assumption is made that the supplied * 61 * filename is a constant string. A duplicate of the filename string is not created since * 62 * it would be wasteful in that case. * 63 * * 64 * INPUT: filename -- The filename to assign to this file object. * 65 * * 66 * OUTPUT: none * 67 * * 68 * WARNINGS: none * 69 * * 70 * HISTORY: * 71 * 11/10/1995 DRD : Created. * 72 *=============================================================================================*/ 73 BufferIOFileClass::BufferIOFileClass(char const * filename) : 74 IsAllocated(false), 75 IsOpen(false), 76 IsDiskOpen(false), 77 IsCached(false), 78 IsChanged(false), 79 UseBuffer(false), 80 BufferRights(0), 81 Buffer(0), 82 BufferSize(0), 83 BufferPos(0), 84 BufferFilePos(0), 85 BufferChangeBeg(-1), 86 BufferChangeEnd(-1), 87 FileSize(0), 88 FilePos(0), 89 TrueFileStart(0) 90 { 91 BufferIOFileClass::Set_Name(filename); 92 } 93 94 95 /*********************************************************************************************** 96 * BufferIOFileClass::BufferIOFileClass -- default constructor for a file object. * 97 * * 98 * This is the default constructor for a file object. * 99 * * 100 * INPUT: none * 101 * * 102 * OUTPUT: none * 103 * * 104 * WARNINGS: none * 105 * * 106 * HISTORY: * 107 * 11/10/1995 DRD : Created. * 108 *=============================================================================================*/ 109 BufferIOFileClass::BufferIOFileClass(void) : 110 IsAllocated(false), 111 IsOpen(false), 112 IsDiskOpen(false), 113 IsCached(false), 114 IsChanged(false), 115 UseBuffer(false), 116 BufferRights(0), 117 Buffer(0), 118 BufferSize(0), 119 BufferPos(0), 120 BufferFilePos(0), 121 BufferChangeBeg(-1), 122 BufferChangeEnd(-1), 123 FileSize(0), 124 FilePos(0), 125 TrueFileStart(0) 126 { 127 } 128 129 130 /*********************************************************************************************** 131 * BufferIOFileClass::~BufferIOFileClass -- Destructor for the file object. * 132 * * 133 * This destructor will free all memory allocated thru using Cache routines. * 134 * * 135 * INPUT: none * 136 * * 137 * OUTPUT: none * 138 * * 139 * WARNINGS: none * 140 * * 141 * HISTORY: * 142 * 11/10/1995 DRD : Created. * 143 *=============================================================================================*/ 144 BufferIOFileClass::~BufferIOFileClass(void) 145 { 146 Free(); 147 } 148 149 150 /*********************************************************************************************** 151 * BufferIOFileClass::Cache -- Load part or all of a file data into RAM. * 152 * * 153 * INPUT: none * 154 * * 155 * OUTPUT: bool; Was the file load successful? It could fail if there wasn't enough room * 156 * to allocate the raw data block. * 157 * * 158 * WARNINGS: This routine goes to disk for a potentially very long time. * 159 * * 160 * HISTORY: * 161 * 11/10/1995 DRD : Created. * 162 *=============================================================================================*/ 163 bool BufferIOFileClass::Cache( long size, void * ptr ) 164 { 165 if (Buffer) { 166 // 167 // if trying to cache again with size or ptr fail 168 // 169 if (size || ptr) { 170 return( false ); 171 } else { 172 return( true ); 173 } 174 } 175 176 if ( Is_Available() ) { 177 FileSize = Size(); 178 } else { 179 FileSize = 0; 180 } 181 182 if (size) { 183 // 184 // minimum buffer size for performance 185 // 186 if (size < MINIMUM_BUFFER_SIZE) { 187 size = MINIMUM_BUFFER_SIZE; 188 189 /* 190 ** Specifying a size smaller than the minimum is an error 191 ** IF a buffer pointer was also specified. In such a case the 192 ** system cannot use the buffer. 193 */ 194 if (ptr) { 195 Error(EINVAL); 196 } 197 } 198 199 BufferSize = size; 200 } else { 201 BufferSize = FileSize; 202 } 203 204 // 205 // if size == 0 and a ptr to a buffer is specified then that is invalid. 206 // if the BufferSize is 0 then this must be a new file and no size was 207 // specified so exit. 208 // 209 if ( (size == 0 && ptr) || !BufferSize) { 210 return( false ); 211 } 212 213 if (ptr) { 214 Buffer = ptr; 215 } else { 216 Buffer = new char [BufferSize]; 217 } 218 219 if (Buffer) { 220 IsAllocated = true; 221 IsDiskOpen = false; 222 BufferPos = 0; 223 BufferFilePos = 0; 224 BufferChangeBeg = -1; 225 BufferChangeEnd = -1; 226 FilePos = 0; 227 TrueFileStart = 0; 228 229 // 230 // the file was checked for availability then set the FileSize 231 // 232 if (FileSize) { 233 long readsize; 234 int opened = false; 235 long prevpos = 0; 236 237 238 if (FileSize <= BufferSize) { 239 readsize = FileSize; 240 } else { 241 readsize = BufferSize; 242 } 243 244 if ( Is_Open() ) { 245 // 246 // get previous file position 247 // 248 prevpos = Seek(0); 249 250 // 251 // get true file position 252 // 253 if ( RawFileClass::Is_Open() ) { 254 TrueFileStart = RawFileClass::Seek(0); 255 } else { 256 TrueFileStart = prevpos; 257 } 258 259 if (FileSize <= BufferSize) { 260 // 261 // if previous position is non-zero seek to the beginning 262 // 263 if (prevpos) { 264 Seek(0, SEEK_SET); 265 } 266 267 // 268 // set the buffer position for future reads/writes 269 // 270 BufferPos = prevpos; 271 } else { 272 BufferFilePos = prevpos; 273 } 274 275 FilePos = prevpos; 276 } else { 277 if ( Open() ) { 278 TrueFileStart = RawFileClass::Seek(0); 279 opened = true; 280 } 281 } 282 283 long actual = Read(Buffer, readsize); 284 285 if (actual != readsize) { 286 Error(EIO); 287 } 288 289 if (opened) { 290 Close(); 291 } else { 292 // 293 // seek to the previous position in the file 294 // 295 Seek(prevpos, SEEK_SET); 296 } 297 298 IsCached = true; 299 } 300 301 UseBuffer = true; 302 return(true); 303 } 304 305 Error(ENOMEM); 306 307 return(false); 308 } 309 310 311 /*********************************************************************************************** 312 * BufferIOFileClass::Free -- Frees the allocated buffer. * 313 * * 314 * This routine will free the buffer. By using this in conjunction with the * 315 * Cache() function, one can maintain tight control of memory usage. * 316 * * 317 * INPUT: none * 318 * * 319 * OUTPUT: none * 320 * * 321 * WARNINGS: none * 322 * * 323 * HISTORY: * 324 * 11/10/1995 DRD : Created. * 325 *=============================================================================================*/ 326 void BufferIOFileClass::Free(void) 327 { 328 if (Buffer) { 329 if (IsAllocated) { 330 delete [] Buffer; 331 IsAllocated = false; 332 } 333 334 Buffer = 0; 335 } 336 337 BufferSize = 0; 338 IsOpen = false; 339 IsCached = false; 340 IsChanged = false; 341 UseBuffer = false; 342 } 343 344 345 /*********************************************************************************************** 346 * BufferIOFileClass::Commit -- Writes the cache to the file if it has changed. * 347 * * 348 * * 349 * INPUT: none * 350 * * 351 * OUTPUT: false, did not need to write the buffer. * 352 * true, wrote the buffer. * 353 * * 354 * WARNINGS: none * 355 * * 356 * HISTORY: * 357 * 11/15/1995 DRD : Created. * 358 *=============================================================================================*/ 359 bool BufferIOFileClass::Commit( void ) 360 { 361 long size; 362 363 364 if (UseBuffer) { 365 if (IsChanged) { 366 size = BufferChangeEnd - BufferChangeBeg; 367 368 if (IsDiskOpen) { 369 RawFileClass::Seek( TrueFileStart + BufferFilePos + 370 BufferChangeBeg, SEEK_SET ); 371 RawFileClass::Write( Buffer, size ); 372 RawFileClass::Seek( TrueFileStart + FilePos, SEEK_SET ); 373 } else { 374 RawFileClass::Open(); 375 RawFileClass::Seek( TrueFileStart + BufferFilePos + 376 BufferChangeBeg, SEEK_SET ); 377 RawFileClass::Write( Buffer, size ); 378 RawFileClass::Close(); 379 } 380 381 IsChanged = false; 382 return( true ); 383 } else { 384 return( false ); 385 } 386 } else { 387 return( false ); 388 } 389 } 390 391 392 /*********************************************************************************************** 393 * BufferIOFileClass::Set_Name -- Checks for name changed for a cached file. * 394 * * 395 * Checks for a previous filename and that it is cached. If so, then check the * 396 * new filename against the old. If they are the same then return that filename. * 397 * Otherwise, the file object's name is set with just the raw filename as passed * 398 * to this routine. * 399 * * 400 * INPUT: filename -- Pointer to the filename to set as the name of this file object. * 401 * * 402 * OUTPUT: Returns a pointer to the final and complete filename of this file object. This * 403 * may have a path attached to the file. * 404 * * 405 * WARNINGS: none * 406 * * 407 * HISTORY: * 408 * 11/15/1995 DRD : Created. * 409 *=============================================================================================*/ 410 char const * BufferIOFileClass::Set_Name(char const * filename) 411 { 412 if ( File_Name() && UseBuffer) { 413 if ( strcmp(filename, File_Name() ) == 0) { 414 return( File_Name() ); 415 } else { 416 Commit(); 417 IsCached = false; 418 } 419 } 420 421 RawFileClass::Set_Name(filename); 422 return( File_Name() ); 423 } 424 425 426 /*********************************************************************************************** 427 * BufferIOFileClass::Is_Available -- Checks for existence of file cached or on disk. * 428 * * 429 * * 430 * INPUT: none * 431 * * 432 * OUTPUT: bool; Is the file available for opening? * 433 * * 434 * WARNINGS: none * 435 * * 436 * HISTORY: * 437 * 11/16/1995 DRD : Created. * 438 *=============================================================================================*/ 439 int BufferIOFileClass::Is_Available(int ) 440 { 441 if (UseBuffer) { 442 return(true); 443 } 444 445 return( RawFileClass::Is_Available() ); 446 } 447 448 449 /*********************************************************************************************** 450 * BufferIOFileClass::Is_Open -- Determines if the file is open. * 451 * * 452 * If part or all of the file is cached, then return that it is opened. A closed file * 453 * doesn't have a valid pointer. * 454 * * 455 * INPUT: none * 456 * * 457 * OUTPUT: bool; Is the file open? * 458 * * 459 * WARNINGS: none * 460 * * 461 * HISTORY: * 462 * 11/14/1995 DRD : Created. * 463 *=============================================================================================*/ 464 int BufferIOFileClass::Is_Open(void) const 465 { 466 if (IsOpen && UseBuffer) { 467 return( true ); 468 } 469 470 return( RawFileClass::Is_Open() ); 471 } 472 473 474 /*********************************************************************************************** 475 * BufferIOFileClass::Open -- Assigns name and opens file in one operation. * 476 * * 477 * This routine will assign the specified filename to the file object and open it at the * 478 * same time. If the file object was already open, then it will be closed first. If the * 479 * file object was previously assigned a filename, then it will be replaced with the new * 480 * name. Typically, this routine is used when an anonymous file object has been crated and * 481 * now it needs to be assigned a name and opened. * 482 * * 483 * INPUT: filename -- The filename to assign to this file object. * 484 * * 485 * rights -- The open file access rights to use. * 486 * * 487 * OUTPUT: bool; Was the file opened? The return value of this is moot, since the open file * 488 * is designed to never return unless it succeeded. * 489 * * 490 * WARNINGS: none * 491 * * 492 * HISTORY: * 493 * 11/14/1995 DRD : Created. * 494 *=============================================================================================*/ 495 int BufferIOFileClass::Open(char const * filename, int rights) 496 { 497 Set_Name(filename); 498 return( BufferIOFileClass::Open( rights ) ); 499 } 500 501 502 /*********************************************************************************************** 503 * BufferIOFileClass::Open -- Opens the file object with the rights specified. * 504 * * 505 * This routine is used to open the specified file object with the access rights indicated. * 506 * This only works if the file has already been assigned a filename. It is guaranteed, by * 507 * the error handler, that this routine will always return with success. * 508 * * 509 * INPUT: rights -- The file access rights to use when opening this file. This is a * 510 * combination of READ and/or WRITE bit flags. * 511 * * 512 * OUTPUT: bool; Was the file opened successfully? This will always return true by reason of * 513 * the error handler. * 514 * * 515 * WARNINGS: none * 516 * * 517 * HISTORY: * 518 * 11/14/1995 DRD : Created. * 519 *=============================================================================================*/ 520 int BufferIOFileClass::Open(int rights) 521 { 522 BufferIOFileClass::Close(); 523 524 if (UseBuffer) { 525 526 BufferRights = rights; // save rights requested for checks later 527 528 if (rights != READ || 529 (rights == READ && FileSize > BufferSize) ) { 530 531 if (rights == WRITE) { 532 RawFileClass::Open( rights ); 533 RawFileClass::Close(); 534 rights = READ | WRITE; 535 TrueFileStart = 0; // now writing to single file 536 } 537 538 if (TrueFileStart) { 539 UseBuffer = false; 540 Open( rights ); 541 UseBuffer = true; 542 } else { 543 RawFileClass::Open( rights ); 544 } 545 546 IsDiskOpen = true; 547 548 if (BufferRights == WRITE) { 549 FileSize = 0; 550 } 551 552 } else { 553 IsDiskOpen = false; 554 } 555 556 BufferPos = 0; 557 BufferFilePos = 0; 558 BufferChangeBeg = -1; 559 BufferChangeEnd = -1; 560 FilePos = 0; 561 IsOpen = true; 562 } else { 563 RawFileClass::Open( rights ); 564 } 565 566 return( true ); 567 } 568 569 570 /*********************************************************************************************** 571 * BufferIOFileClass::Write -- Writes data to the file cache. * 572 * * 573 * * 574 * INPUT: buffer -- Pointer to the buffer that holds the data to be written. * 575 * * 576 * size -- The number of bytes to write. * 577 * * 578 * OUTPUT: Returns the number of bytes actually written. * 579 * * 580 * WARNINGS: none * 581 * * 582 * HISTORY: * 583 * 11/15/1995 DRD : Created. * 584 *=============================================================================================*/ 585 long BufferIOFileClass::Write(void const * buffer, long size) 586 { 587 int opened = false; 588 589 if ( !Is_Open() ) { 590 if (!Open(WRITE)) { 591 return(0); 592 } 593 TrueFileStart = RawFileClass::Seek(0); 594 opened = true; 595 } 596 597 if (UseBuffer) { 598 long sizewritten = 0; 599 600 if (BufferRights != READ) { 601 while (size) { 602 long sizetowrite; 603 604 if (size >= (BufferSize - BufferPos) ) { 605 sizetowrite = (BufferSize - BufferPos); 606 } else { 607 sizetowrite = size; 608 } 609 610 if (sizetowrite != BufferSize) { 611 612 if ( !IsCached ) { 613 long readsize; 614 615 if (FileSize < BufferSize) { 616 readsize = FileSize; 617 BufferFilePos = 0; 618 } else { 619 readsize = BufferSize; 620 BufferFilePos = FilePos; 621 } 622 623 if (TrueFileStart) { 624 UseBuffer = false; 625 Seek( FilePos, SEEK_SET ); 626 Read( Buffer, BufferSize ); 627 Seek( FilePos, SEEK_SET ); 628 UseBuffer = true; 629 } else { 630 RawFileClass::Seek( BufferFilePos, SEEK_SET ); 631 RawFileClass::Read( Buffer, readsize ); 632 } 633 634 BufferPos = 0; 635 BufferChangeBeg = -1; 636 BufferChangeEnd = -1; 637 638 IsCached = true; 639 } 640 } 641 642 memmove((char *)Buffer + BufferPos, (char *)buffer + sizewritten, sizetowrite); 643 644 IsChanged = true; 645 sizewritten += sizetowrite; 646 size -= sizetowrite; 647 648 if (BufferChangeBeg == -1) { 649 BufferChangeBeg = BufferPos; 650 BufferChangeEnd = BufferPos; 651 } else { 652 if (BufferChangeBeg > BufferPos) { 653 BufferChangeBeg = BufferPos; 654 } 655 } 656 657 BufferPos += sizetowrite; 658 659 if (BufferChangeEnd < BufferPos) { 660 BufferChangeEnd = BufferPos; 661 } 662 663 FilePos = BufferFilePos + BufferPos; 664 665 if (FileSize < FilePos) { 666 FileSize = FilePos; 667 } 668 669 // 670 // end of buffer reached? 671 // 672 if (BufferPos == BufferSize) { 673 Commit(); 674 675 BufferPos = 0; 676 BufferFilePos = FilePos; 677 BufferChangeBeg = -1; 678 BufferChangeEnd = -1; 679 680 if (size && FileSize > FilePos) { 681 if (TrueFileStart) { 682 UseBuffer = false; 683 Seek( FilePos, SEEK_SET ); 684 Read( Buffer, BufferSize ); 685 Seek( FilePos, SEEK_SET ); 686 UseBuffer = true; 687 } else { 688 RawFileClass::Seek( FilePos, SEEK_SET ); 689 RawFileClass::Read( Buffer, BufferSize ); 690 } 691 } else { 692 IsCached = false; 693 } 694 } 695 } 696 } else { 697 Error(EACCES); 698 } 699 700 size = sizewritten; 701 } else { 702 size = RawFileClass::Write(buffer, size); 703 } 704 705 if (opened) { 706 Close(); 707 } 708 709 return( size ); 710 } 711 712 713 /*********************************************************************************************** 714 * BufferIOFileClass::Read -- Reads data from the file cache. * 715 * * 716 * * 717 * INPUT: buffer -- Pointer to the buffer to place the read data. * 718 * * 719 * size -- The number of bytes to read. * 720 * * 721 * OUTPUT: Returns the actual number of bytes read (this could be less than requested). * 722 * * 723 * WARNINGS: none * 724 * * 725 * HISTORY: * 726 * 11/15/1995 DRD : Created. * 727 *=============================================================================================*/ 728 long BufferIOFileClass::Read(void * buffer, long size) 729 { 730 int opened = false; 731 732 if ( !Is_Open() ) { 733 if ( Open() ) { 734 TrueFileStart = RawFileClass::Seek(0); 735 opened = true; 736 } 737 } 738 739 if (UseBuffer) { 740 long sizeread = 0; 741 742 if (BufferRights != WRITE) { 743 while (size) { 744 long sizetoread; 745 746 if (size >= (BufferSize - BufferPos) ) { 747 sizetoread = (BufferSize - BufferPos); 748 } else { 749 sizetoread = size; 750 } 751 752 if ( !IsCached ) { 753 long readsize; 754 755 if (FileSize < BufferSize) { 756 readsize = FileSize; 757 BufferFilePos = 0; 758 } else { 759 readsize = BufferSize; 760 BufferFilePos = FilePos; 761 } 762 763 if (TrueFileStart) { 764 UseBuffer = false; 765 Seek( FilePos, SEEK_SET ); 766 Read( Buffer, BufferSize ); 767 Seek( FilePos, SEEK_SET ); 768 UseBuffer = true; 769 } else { 770 RawFileClass::Seek( BufferFilePos, SEEK_SET ); 771 RawFileClass::Read( Buffer, readsize ); 772 } 773 774 BufferPos = 0; 775 BufferChangeBeg = -1; 776 BufferChangeEnd = -1; 777 778 IsCached = true; 779 } 780 781 memmove((char *)buffer + sizeread, (char *)Buffer + BufferPos, sizetoread); 782 783 sizeread += sizetoread; 784 size -= sizetoread; 785 BufferPos += sizetoread; 786 FilePos = BufferFilePos + BufferPos; 787 788 // 789 // end of buffer reached? 790 // 791 if (BufferPos == BufferSize) { 792 Commit(); 793 794 BufferPos = 0; 795 BufferFilePos = FilePos; 796 BufferChangeBeg = -1; 797 BufferChangeEnd = -1; 798 799 if (size && FileSize > FilePos) { 800 if (TrueFileStart) { 801 UseBuffer = false; 802 Seek( FilePos, SEEK_SET ); 803 Read( Buffer, BufferSize ); 804 Seek( FilePos, SEEK_SET ); 805 UseBuffer = true; 806 } else { 807 RawFileClass::Seek( FilePos, SEEK_SET ); 808 RawFileClass::Read( Buffer, BufferSize ); 809 } 810 } else { 811 IsCached = false; 812 } 813 } 814 } 815 } else { 816 Error(EACCES); 817 } 818 819 size = sizeread; 820 } else { 821 size = RawFileClass::Read(buffer, size); 822 } 823 824 if (opened) { 825 Close(); 826 } 827 828 return( size ); 829 } 830 831 832 /*********************************************************************************************** 833 * BufferIOFileClass::Seek -- Moves the current file pointer in the file. * 834 * * 835 * This routine will change the current file pointer to the position specified. It follows * 836 * the same rules the a normal Seek() does, but if the file is part of the mixfile system, * 837 * then only the position value needs to be updated. * 838 * * 839 * INPUT: pos -- The position to move the file to relative to the position indicated * 840 * by the "dir" parameter. * 841 * * 842 * dir -- The direction to affect the position change against. This can be * 843 * either SEEK_CUR, SEEK_END, or SEEK_SET. * 844 * * 845 * OUTPUT: Returns with the position of the new location. * 846 * * 847 * WARNINGS: none * 848 * * 849 * HISTORY: * 850 * 11/15/1995 DRD : Created. * 851 *=============================================================================================*/ 852 long BufferIOFileClass::Seek(long pos, int dir) 853 { 854 if (UseBuffer) { 855 bool adjusted = false; 856 857 switch (dir) { 858 case SEEK_END: 859 FilePos = FileSize; 860 break; 861 862 case SEEK_SET: 863 FilePos = 0; 864 break; 865 866 case SEEK_CUR: 867 default: 868 break; 869 } 870 871 if (TrueFileStart) { 872 if (pos >= TrueFileStart) { 873 pos -= TrueFileStart; 874 adjusted = true; 875 } 876 } 877 878 FilePos += pos; 879 880 if (FilePos < 0) { 881 FilePos = 0; 882 } 883 884 if (FilePos > FileSize ) { 885 FilePos = FileSize; 886 } 887 888 if (FileSize <= BufferSize) { 889 BufferPos = FilePos; 890 } else { 891 if (FilePos >= BufferFilePos && 892 FilePos < (BufferFilePos + BufferSize) ) { 893 BufferPos = FilePos - BufferFilePos; 894 } else { 895 Commit(); 896 // check!! 897 if (TrueFileStart) { 898 UseBuffer = false; 899 Seek(FilePos, SEEK_SET); 900 UseBuffer = true; 901 } else { 902 RawFileClass::Seek(FilePos, SEEK_SET); 903 } 904 905 IsCached = false; 906 } 907 } 908 909 if (TrueFileStart && adjusted) { 910 return( FilePos + TrueFileStart ); 911 } 912 913 return( FilePos ); 914 } 915 916 return( RawFileClass::Seek(pos, dir) ); 917 } 918 919 920 /*********************************************************************************************** 921 * BufferIOFileClass::Size -- Determines size of file (in bytes). * 922 * * 923 * If part or all of the file is cached, then the size of the file is already * 924 * determined and available. Otherwise, go to the low level system to find the file * 925 * size. * 926 * * 927 * INPUT: none * 928 * * 929 * OUTPUT: Returns with the number of bytes in the file. * 930 * * 931 * WARNINGS: none * 932 * * 933 * HISTORY: * 934 * 11/14/1995 DRD : Created. * 935 *=============================================================================================*/ 936 long BufferIOFileClass::Size(void) 937 { 938 if (IsOpen && UseBuffer) { 939 return( FileSize ); 940 } 941 942 return( RawFileClass::Size() ); 943 } 944 945 946 /*********************************************************************************************** 947 * BufferIOFileClass::Close -- Perform a closure of the file. * 948 * * 949 * Call Commit() to write the buffer if the file is cached and the buffer has changed, * 950 * then call lower level Close(). * 951 * * 952 * INPUT: none * 953 * * 954 * OUTPUT: none * 955 * * 956 * WARNINGS: none * 957 * * 958 * HISTORY: * 959 * 11/14/1995 DRD : Created. * 960 *=============================================================================================*/ 961 void BufferIOFileClass::Close(void) 962 { 963 if (UseBuffer) { 964 Commit(); 965 966 if (IsDiskOpen) { 967 968 if (TrueFileStart) { 969 UseBuffer = false; 970 Close(); 971 UseBuffer = true; 972 } else { 973 RawFileClass::Close(); 974 } 975 976 IsDiskOpen = false; 977 } 978 979 IsOpen = false; 980 } else { 981 RawFileClass::Close(); 982 } 983 } 984