home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / c / WLIB.ZIP / WFILE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-12  |  11.4 KB  |  575 lines

  1. #include <ctype.h>
  2. #include <WStr.h>
  3. #include <WFile.h>
  4. #ifdef MAJORBBS
  5.   extern "C"
  6.     {
  7.       #include <gcomm.h>
  8.     }
  9. #endif
  10. #pragma hdrstop
  11.  
  12. // copyright (c) 1992, 1993 by Paul Wheaton
  13.  
  14. //.parse
  15.  
  16. void LowLevelFile::InternalInit(int BufSize)
  17.   {
  18.     if (FilePointer==NULL) FatalError("LLFileCtor2:"+String120(GivenFileName));
  19.     Open=True;
  20.     if ((BufSize==BUFSIZ)||(BufSize==0)) Buf=NULL;
  21.     else
  22.       {
  23.         #ifdef MAJORBBS
  24.           Buf=(char*)malloc(BufSize);
  25.           if (Buf!=NULL) setvbuf(FilePointer,Buf,_IOFBF,size_t(BufSize));
  26.         #else
  27.           Buf=new char[BufSize];
  28.           if (Buf==NULL) Beep();
  29.           else setvbuf(FilePointer,Buf,_IOFBF,size_t(BufSize));
  30.         #endif
  31.       }
  32.   }
  33.  
  34. //.parse
  35.  
  36. LowLevelFile::LowLevelFile(const char* FileName, const char* Mode,int BufSize)
  37.   {
  38.     GivenFileName=(char*)FileName;
  39.     if (!FileExists(FileName))
  40.       {
  41.         FILE* P=fopen(FileName,"wb");
  42.         if (P==NULL) FatalError("LLFileCtor1:"+String120(FileName));
  43.         fclose(P);
  44.       }
  45.     FilePointer=fopen(FileName,Mode);
  46.     InternalInit(BufSize);
  47.   }
  48.  
  49. /*
  50.  
  51. LowLevelFile::LowLevelFile(const char* FileName,FileShareType FS,
  52.     const char* Mode,int BufSize)
  53.   {
  54.     GivenFileName=(char*)FileName;
  55.     if (!FileExists(FileName))
  56.       {
  57.         FILE* P=fsopen(FileName,"wb");
  58.         if (P==NULL) FatalError("LLFileCtor1:"+String120(FileName));
  59.         fclose(P);
  60.       }
  61.     FilePointer=fsopen(FileName,Mode);
  62.     InternalInit(BufSize);
  63.   }
  64. */
  65.  
  66. //.parse
  67.  
  68. void LowLevelFile::Close()
  69.   {
  70.     if (Open)
  71.       {
  72.         Open=False;
  73.         fclose(FilePointer);
  74.         #ifdef MAJORBBS
  75.           if (Buf) free(Buf);
  76.         #else
  77.           if (Buf) delete Buf;
  78.         #endif
  79.       }
  80.   }
  81.  
  82. //.parse
  83.  
  84. long LowLevelFile::Size()
  85.   {
  86.     long P=CurPos();
  87.     Flush();
  88.     long S=filelength(fileno(FilePointer));
  89.     Seek(P);
  90.     return(S);
  91.   }
  92.  
  93. //.parse
  94.  
  95. File::File(const char* FileName,Bool Mode,int BufSize):
  96.       LowLevelFile(FileName,((Mode==ReadOnly)?("rb"):("r+b")),BufSize)
  97.   {}
  98.  
  99. //.parse
  100.  
  101. Bool File::Read(void *Buffer,int Size)
  102.   {
  103.     char* P=(char*)Buffer;
  104.     Bool ReturnVal=True;
  105.     while((ReturnVal==True)&&(Size>0))
  106.       {
  107.         int X=Min(Size,512);
  108.         ReturnVal=(fread(P,X,1,FilePointer)==1);
  109.         Size-=X;
  110.         P+=X;
  111.       }
  112.     return ReturnVal;
  113.   }
  114.  
  115. //.parse
  116.  
  117. void File::Write(const void *Buffer,int Size)
  118.   {
  119.     const char* P=(const char*)Buffer;
  120.     while(Size>0)
  121.       {
  122.         int X=Min(Size,512);
  123.         fwrite(P,X,1,FilePointer);
  124.         Size-=X;
  125.         P+=X;
  126.       }
  127.   }
  128.  
  129. //.parse
  130.  
  131. Bool File::Read(ByteVector& BV,int Size)
  132.   {
  133.     if (BV.Capacity()<Size) BV.ReAlloc(Size);
  134.     BV.Len=Size;
  135.     return Read((void*)BV.P,Size);
  136.   }
  137.  
  138. //.parse
  139.  
  140. void TextFile::Write(const char* S)
  141.   {
  142.     if (!Started)
  143.       {
  144.         Started=True;
  145.         SeekEOF();
  146.       }
  147.     #ifdef MAJORBBS
  148.       /*
  149.       while (*S)
  150.         {
  151.           if (fputc(*S,FilePointer)==EOF) FatalError("tfwrite");
  152.           S++;
  153.         }
  154.       */
  155.       if (fprintf(FilePointer,S)<0) FatalError("tfwrite");
  156.     #else
  157.       if (fputs(S,FilePointer)<0) FatalError("tfwrite");
  158.     #endif
  159.   }
  160.  
  161. void TextFile::WriteLine(const char* S)
  162.   {
  163.     Write(S);
  164.     Write("\n");
  165.   }
  166.  
  167. //.parse
  168.  
  169. Bool TextFile::Read(char* S)
  170.   {
  171.     if (!Started)
  172.       {
  173.         Started=True;
  174.         SeekBOF();
  175.       }
  176.     if (fgets(S,MaxInt,FilePointer)!=NULL)
  177.       {
  178.         int L=strlen(S);
  179.         if (L>0)
  180.           {
  181.             if (S[L-1]=='\n') S[L-1]='\0';
  182.           }
  183.         else S[0]='\0';
  184.         return(True);
  185.       }
  186.     else
  187.       {
  188.         S[0]='\0';
  189.         return(False);
  190.       }
  191.   }
  192.  
  193. //.parse
  194.  
  195. void DeleteFile(const char* FileName)
  196.   {
  197.     if (FileExists(FileName)) unlink(FileName);
  198.   }
  199.  
  200. //.parse
  201.  
  202. void FileCopying(File& DFile, File& SFile, long Size)
  203.   {
  204.     const BufSize=512;
  205.     Byte Buf[BufSize];
  206.     while (Size>0)
  207.       {
  208.         long Chunk=Min(Size,long(BufSize));
  209.         SFile.Read(&Buf[0],int(Chunk));
  210.         DFile.Write(&Buf[0],int(Chunk));
  211.         Size-=Chunk;
  212.       }
  213.   }
  214.  
  215. //.parse
  216.  
  217. Word CRC(File& F)
  218.   {
  219.     F.Seek(0);
  220.     return CRC(F,F.Size());
  221.   }
  222.  
  223. const Word CRCMask=0x1021; // crc-ccitt mask
  224.  
  225. Word CRC(File& F,long FSize)
  226.   {
  227.     Word X=0;
  228.     long I;
  229.     For(I,FSize)
  230.       {
  231.         char Ch;
  232.         F.ReadThing(Ch);
  233.         int Z=Ch;
  234.         Z<<=8;
  235.         int J;
  236.         For(J,8)
  237.           {
  238.             if((X ^ Z) & 0x8000) X=(X<<1)^CRCMask;
  239.             else X<<=1;
  240.             Z<<=1;
  241.           }
  242.       }
  243.     return X;
  244.   }
  245.  
  246. //.parse
  247.  
  248. #ifdef MAJORBBS
  249.  
  250.   Bool FileExists(const char* Name)
  251.     {
  252.       fndblk FF;
  253.       Bool Found=(fnd1st(&FF,(char*)Name,0)==1);
  254.       return Found;
  255.     }
  256.  
  257.   long DiskSpace(const char Drive)
  258.     {
  259.       int D;
  260.       if (Drive=='.') D=0;
  261.       else D=((int(Drive)+1)-int('A'));  // BC byte math not trustworthy
  262.       long X=getdfre(D)/1024;
  263.       return X;
  264.     }
  265.  
  266. #else
  267.  
  268.   char CurDiskDrive()
  269.     {
  270.       unsigned D;
  271.       _dos_getdrive(&D);
  272.       char C=char(D+'A'-1);
  273.       return C;
  274.     }
  275.  
  276.   long DiskSpace(const char Drive)
  277.     {
  278.       char D;
  279.       if (Drive=='.') D='\0';
  280.       else D=char((int(toupper(Drive))+1)-int('A'));  // BC byte math not trustworthy
  281.       struct diskfree_t F;
  282.       long X=0;
  283.       if (_dos_getdiskfree(D,&F)==0)
  284.         {
  285.           X=long(F.avail_clusters)*long(F.bytes_per_sector)*long(F.sectors_per_cluster);
  286.           X/=1024;
  287.         }
  288.       return X;
  289.     }
  290.  
  291. #endif
  292.  
  293. //.parse
  294.  
  295. long FileSize(const char* FileName)
  296.   {
  297.     long X=0;
  298.     if (FileExists(FileName))
  299.       {
  300.         File F(FileName,ReadOnly);
  301.         X=F.Size();
  302.       }
  303.     return X;
  304.   }
  305.  
  306. //.parse
  307.  
  308. void CopyFile(const char* DestFile, const char* SourceFile)
  309.   {
  310.     DeleteFile(DestFile);
  311.     File DF(DestFile);
  312.     File SF(SourceFile,ReadOnly);
  313.     FileCopying(DF,SF,SF.Size());
  314.   }
  315.  
  316. //.parse
  317.  
  318. RecFile::RecFile(const char* FileName,int RecordSize,Bool Mode,int BufSize):
  319.       LowLevelFile(FileName,((Mode==ReadOnly)?("rb"):("r+b")),BufSize)
  320.   {
  321.     RecSize=RecordSize;
  322.   }
  323.  
  324. //.parse
  325.  
  326. Bool RecFile::Read(void *Buffer)
  327.   {
  328.     return (fread(Buffer,RecSize,1,FilePointer)==1);
  329.   }
  330.  
  331. //.parse
  332.  
  333. void RecFile::Write(const void *Buffer)
  334.   {
  335.     fwrite(Buffer,RecSize,1,FilePointer);
  336.   }
  337.  
  338. //.parse
  339.  
  340. Bool RecFile::Read(void *Buffer,int S)
  341.   {
  342.     return (fread(Buffer,RecSize*S,1,FilePointer)==1);
  343.   }
  344.  
  345. //.parse
  346.  
  347. void RecFile::Write(const void *Buffer,int S)
  348.   {
  349.     fwrite(Buffer,RecSize*S,1,FilePointer);
  350.   }
  351.  
  352. //.parse
  353.  
  354. void RecFile::Seek(long RecNum)
  355.   {
  356.     LowLevelFile::Seek(RecNum*RecSize);
  357.   }
  358.  
  359. //.parse
  360.  
  361. long RecFile::Size()
  362.   {
  363.     return LowLevelFile::Size()/RecSize;
  364.   }
  365.  
  366. //.parse
  367.  
  368. long RecFile::CurRec()
  369.   {
  370.     return LowLevelFile::CurPos()/RecSize;
  371.   }
  372.  
  373. //.parse
  374.  
  375. Bool TokenFile::TokenExists(Word Token)
  376.   {
  377.     if (!InRange(Token,Word(1),MaxTokens)) return False;
  378.     SeekIndexSlot(Token);
  379.     long Pos;
  380.     ReadThing(Pos);
  381.     return(Pos!=0);
  382.   }
  383.  
  384. //.parse
  385.  
  386. void TokenFile::GetFreeInfo(long Pos, long& Size, long& NextBlock)
  387.   {
  388.     File::Seek(Pos);
  389.     ReadThing(Size);
  390.     ReadThing(NextBlock);
  391.   }
  392.  
  393. //.parse
  394.  
  395. long TokenFile::New(long FSize)
  396.   {
  397.     long CurBlock=FirstFreeBlock;
  398.     long LastBlock=0;
  399.     while (CurBlock)
  400.       {
  401.         long CurSize;
  402.         long NextBlock;
  403.         GetFreeInfo(CurBlock,CurSize,NextBlock);
  404.         if (CurSize<FSize)
  405.           {
  406.             LastBlock=CurBlock;
  407.             CurBlock=NextBlock;
  408.           }
  409.         else  // a fit!
  410.           {
  411.             // take off of free list
  412.             if (LastBlock) // make free list skip this block
  413.               {
  414.                 Flush();
  415.                 File::Seek(LastBlock+4);
  416.                 File::WriteThing(NextBlock);
  417.                 Flush();
  418.               }
  419.             else // make start of free list point to next element of list
  420.               {
  421.                 FirstFreeBlock=NextBlock;
  422.                 Flush();
  423.                 File::Seek(0);
  424.                 File::WriteThing(FirstFreeBlock);
  425.                 Flush();
  426.               }
  427.             if (CurSize>FSize) // add leftovers to free list
  428.                 Delete(CurBlock+FSize,CurSize-FSize);
  429.             File::Seek(CurBlock);
  430.             return(CurBlock);
  431.           }
  432.       }
  433.     // return the block num for appending to EOF
  434.     File::Seek(Size());
  435.     return (Size());
  436.   }
  437.  
  438. //.parse
  439.  
  440. void TokenFile::Delete(long Pos, long Size)
  441.   {
  442.     if (Size<8) return; // too small to mess with
  443.     Flush();
  444.     File::Seek(0);
  445.     File::WriteThing(Pos);
  446.     File::Seek(Pos);
  447.     File::WriteThing(Size);
  448.     File::WriteThing(FirstFreeBlock);
  449.     Flush();
  450.     FirstFreeBlock=Pos;
  451.   }
  452.  
  453. //.parse
  454.  
  455. void TokenFile::Delete(Word Token)
  456.   {
  457.     if (!InRange(Token,Word(1),MaxTokens)) return;
  458.     SeekIndexSlot(Token);
  459.     long Pos,Size;
  460.     ReadCurIndexSlot(Pos,Size);
  461.     if (Pos)
  462.       {
  463.         Delete(Pos,Size);
  464.         Pos=0;
  465.         Size=0;
  466.         Flush();
  467.         SeekIndexSlot(Token);
  468.         WriteThing(Pos);
  469.         WriteThing(Size);
  470.         Flush();
  471.       }
  472.   }
  473.  
  474. //.parse
  475.  
  476. void TokenFile::WritePrep(Word Token,long DataSize)
  477.   {
  478.     if (!InRange(Token,Word(1),MaxTokens)) return;
  479.     SeekIndexSlot(Token);
  480.     long Pos,CurSize;
  481.     ReadCurIndexSlot(Pos,CurSize);
  482.     if (Pos==0) Pos=New(DataSize);
  483.     else if (CurSize<DataSize)  // can't use this space
  484.       {
  485.         Delete(Pos,CurSize);
  486.         Pos=New(DataSize);
  487.       }
  488.     else if (CurSize>DataSize)  //  can use this space but need to return excess
  489.         Delete(Pos+DataSize,CurSize-DataSize);
  490.     // the last case is that the currently selected block is the perfect size
  491.     // in case Pos or Size ain't what it used to be...
  492.     Flush();
  493.     SeekIndexSlot(Token);
  494.     File::WriteThing(Pos);
  495.     File::WriteThing(DataSize);
  496.     Flush();
  497.     File::Seek(Pos);
  498.   }
  499.  
  500. //.parse
  501.  
  502. TokenFile::TokenFile(const char* FileName,int BufSize):
  503.       File(FileName,ReadAndWrite,BufSize)
  504.   {
  505.     if (Size()==0)
  506.       {
  507.         FirstFreeBlock=0;
  508.         File::WriteThing(FirstFreeBlock);
  509.         const Word MTInit=1000;  // MaxTokens Init
  510.         MaxTokens=MTInit;
  511.         File::WriteThing(MaxTokens);
  512.         Word NotUsed=0;
  513.         File::WriteThing(NotUsed);
  514.         long A[MTInit*2]; //  2 longs per token
  515.         const Word ASize=MTInit*2*4;
  516.         memset(&A[0],0,ASize);
  517.         File::Write(&A[0],ASize);
  518.         Flush();
  519.       }
  520.     else
  521.       {
  522.         File::Seek(0);
  523.         ReadThing(FirstFreeBlock);
  524.         ReadThing(MaxTokens);
  525.       }
  526.   }
  527.  
  528. //.parse
  529.  
  530. void TokenFile::ReadCurIndexSlot(long& Pos, long& Size)
  531.   {
  532.     ReadThing(Pos);
  533.     ReadThing(Size);
  534.   }
  535.  
  536. //.parse
  537.  
  538. long TokenFile::Seek(Word Token)
  539.   {
  540.     if (!InRange(Token,Word(1),MaxTokens)) return 0;
  541.     SeekIndexSlot(Token);
  542.     long Pos,Size;
  543.     ReadCurIndexSlot(Pos,Size);
  544.     if (Pos>0)
  545.       {
  546.         File::Seek(Pos);
  547.         return(Size);
  548.       }
  549.     return (0);
  550.   }
  551.  
  552. //.parse
  553.  
  554. void TokenFile::Extract(Word Token,char* FileName)
  555.   {
  556.     DeleteFile(FileName);
  557.     if (TokenExists(Token))
  558.       {
  559.         long Size=Seek(Token);
  560.         File F(FileName);
  561.         FileCopying(F,*this,Size);
  562.       }
  563.   }
  564.  
  565. //.parse
  566.  
  567. Bool TokenExists(const char *FileName,Word Token)
  568.   {
  569.     if (!FileExists(FileName)) return False;
  570.     TokenFile F(FileName);
  571.     Bool B=F.TokenExists(Token);
  572.     return B;
  573.   }
  574.  
  575.