findinfile.c

Go to the documentation of this file.
00001 
00002 /*  $Id: findinfile.c 1249 2006-04-11 20:11:18Z andreradke $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "error.h"
00032 #include "memory.h"
00033 #include "strings.h"
00034 #include "file.h"
00035 #include "lang.h"
00036 #include "langinternal.h"
00037 
00038 
00039 
00040 #define filebuffersize  (32 * 1024)     /* 2006-04-10 aradke: updated from 1kB to 32kB for speed */
00041 
00042 
00043 typedef struct tyopenfile {
00044     
00045     tyfilespec fs; /*the file specifier*/
00046     
00047     hdlfilenum fnum; /*the file refnum*/
00048     
00049     Handle hbuffer; /*holds the file data*/
00050     
00051     long ixbuffer; /*points at the next character in the file*/
00052     
00053     long ctbufferbytes; /*number of valid chars in buffer*/
00054     
00055     long ctbytesleft; /*number of valid characters left unread*/
00056     
00057     long fpos; /*current file position*/
00058     
00059     struct tyopenfile **nextfile;
00060     
00061     long refcon;
00062     } tyopenfile, *ptropenfile, **hdlopenfile;
00063     
00064     
00065 hdlopenfile hfirstfile = nil; /*header of file list*/
00066     
00067 
00068 
00069 static boolean loadbufferfromfile (hdlfilenum fnum, Handle hbuffer, long *ctbytes) {
00070 
00071     boolean fl;
00072     long ctread;
00073 
00074     ctread = gethandlesize (hbuffer);
00075     
00076     lockhandle (hbuffer);
00077     
00078     fl = filereaddata (fnum, ctread, ctbytes, *hbuffer);
00079     
00080     unlockhandle (hbuffer);
00081     
00082     return (fl);
00083     } /*loadbufferfromfile*/
00084     
00085     
00086 static boolean backupfilepos (hdlfilenum fnum, long ctbytes) {
00087     
00088     long origfpos, newfpos;
00089     boolean fl;
00090     
00091     filegetposition (fnum, &origfpos);
00092     
00093     if (origfpos >= ctbytes)
00094         newfpos = origfpos - ctbytes;
00095     else
00096         newfpos = 0L;
00097 
00098     fl = filesetposition (fnum, newfpos); 
00099     
00100     /* filegetposition (fnum, &newfpos); */
00101     
00102     return (fl);
00103     } /*backupfilepos*/
00104 
00105 
00106 static void lowercasehandle (Handle h) {
00107     
00108     lowertext ((ptrbyte) *h, gethandlesize (h));
00109     } /*lowercasehandle*/
00110     
00111     
00112 static boolean findopenfile (const tyfilespec *fs, hdlopenfile *hfile, hdlopenfile *hprev) {
00113     
00114     register hdlopenfile x = hfirstfile;
00115     
00116     *hfile = nil;
00117     
00118     *hprev = nil;
00119     
00120     while (true) {
00121         
00122         if (x == nil) /*fell off list*/
00123             return (false);
00124             
00125         if (equalfilespecs (fs, &(**x).fs)) {
00126             
00127             *hfile = x;
00128             
00129             return (true);
00130             }
00131         
00132         *hprev = x;
00133         
00134         x = (**x).nextfile;
00135         } /*while*/
00136     } /*findopenfile*/
00137 
00138 
00139 static void fifopenfileerror (const tyfilespec *fs) {
00140     
00141     /*
00142     5.0.1 dmb: new, additional error reporting
00143     */
00144     
00145     bigstring bsfile;
00146 
00147     getfsfile (fs, bsfile);
00148 
00149     lang2paramerror (filenotopenederror, bsfunctionname, bsfile);
00150     } /*fifopenfileerror*/
00151 
00152 
00153 #if 0
00154 static OSErr openforkperm (const tyfilespec *fs, boolean flresource, short perm, hdlfilenum *fnum) {
00155     
00156     OSErr errcode;
00157     
00158     if (flresource)
00159         errcode = FSpOpenRF (fs, perm, fnum);
00160     else
00161         errcode = FSpOpenDF (fs, perm, fnum);
00162     
00163     return (errcode);
00164     } /*openforkperm*/
00165 #endif
00166 
00167 static boolean fileopener (const tyfilespec *fs, hdlopenfile *hfile, hdlfilenum *fnum) {
00168     
00169     /*
00170     2/13/92 dmb: changed fldontclose logic to something that actually works; 
00171     we no longer ignore opWrErr errors.  instead, we try to open read/write, 
00172     but settle for read only.
00173     
00174     1/25/93 dmb: instead of using fldontclose boolean, we return the hdlopenfile 
00175     if found. the new filecloser uses this to restore things properly
00176     
00177     2.1b6 dmb: generate an oserror when a file can't be opened
00178     */
00179     
00180     boolean fl;
00181     hdlopenfile hprev;
00182     
00183     if (findopenfile (fs, hfile, &hprev)) { /*file was already opened by us*/
00184         
00185         register hdlopenfile hf = *hfile;
00186         long position;
00187         
00188         filegetposition ((**hf).fnum, &position);
00189         
00190         (**hf).fpos = position;
00191         
00192         *fnum = (**hf).fnum;
00193         
00194         return (true);
00195         }
00196     
00197     *hfile = nil;
00198     
00199     disablelangerror ();
00200 
00201     fl = openfile (fs, fnum, false);
00202     
00203     enablelangerror();
00204 
00205     if (!fl)
00206         fl = openfile (fs, fnum, true);
00207 
00208 #ifdef NEWFILESPECTYPE
00209     setoserrorparam ((ptrstring) (*fs).fullSpecifier);
00210 #else
00211     setoserrorparam ((ptrstring) (*fs).name);
00212 #endif
00213     
00214     return (fl);
00215     } /*fileopener*/
00216 
00217 
00218 static boolean fileloadbuffer (hdlopenfile hf) {
00219 
00220     /*
00221     5.1.4 dmb: broke this out of fifread
00222     */
00223     
00224     long ctbytes;
00225     
00226     if (!loadbufferfromfile ((**hf).fnum, (**hf).hbuffer, &ctbytes)) { /*non-EOF error*/
00227         
00228         (**hf).ctbytesleft = 0;
00229         
00230         return (false);
00231         }
00232     
00233     (**hf).ctbufferbytes = ctbytes;
00234     
00235     (**hf).ixbuffer = 0;
00236     
00237     return (true);
00238     } /*fileloadbuffer*/
00239 
00240 
00241 static void filecloser (hdlopenfile hfile, hdlfilenum fnum) {
00242     
00243     if (fnum != 0) {
00244         
00245         if (hfile == nil) /*file wasn't already open*/
00246             closefile (fnum);
00247         
00248         else /*need to restor file position*/
00249             filesetposition (fnum, (**hfile).fpos);
00250         }
00251     } /*filecloser*/
00252 
00253 
00254 boolean fiffindinfile (const tyfilespec *fs, bigstring pattern, long *idx) {
00255     
00256     /*
00257     search for the indicated pattern in the file. return the index that the
00258     match was found at, -1 if not found.
00259     
00260     returns false if there was an error.
00261     
00262     2/2/93 dmb: fixed off-by-one error; last character in string wasn't checked.
00263     
00264     2.1b6 dmb: fixed infinite looping when partial matches were found
00265     */
00266     
00267     hdlfilenum fnum = 0;
00268     short lenpattern;
00269     Handle hbuffer = nil;
00270     long ctbytes;
00271     long fpos = 0;
00272     long oldctbytes;
00273     boolean flreturned = false;
00274     hdlopenfile hfile = nil;
00275     
00276     *idx = -1; /*indicate an error*/
00277     
00278     lenpattern = stringlength (pattern);
00279     
00280     if (lenpattern == 0) { /*no error, but it wasn't found*/
00281         
00282         flreturned = true;
00283         
00284         goto exit;
00285         }
00286         
00287     alllower (pattern); /*search is unicase*/
00288     
00289     if (!fileopener (fs, &hfile, &fnum))
00290         goto exit;
00291         
00292     if (!largefilebuffer (&hbuffer)) /*couldn't allocate minimum buffer*/
00293         goto exit;
00294         
00295     if (!loadbufferfromfile (fnum, hbuffer, &ctbytes))
00296         goto exit;
00297         
00298     if (ctbytes == 0) { /*it's an empty file*/
00299         
00300         flreturned = true;
00301         
00302         goto exit;
00303         }
00304     
00305     oldctbytes = ctbytes;
00306     
00307     while (true) {
00308         
00309         register char *pbuffer = *hbuffer;
00310         register char *pbufferend = pbuffer + ctbytes;
00311         register char chfirst = pattern [1];
00312         
00313         //lockhandle (hbuffer);
00314         
00315         lowercasehandle (hbuffer); /*search is unicase*/
00316         
00317         while (pbuffer < pbufferend) {
00318             
00319             if (*pbuffer++ == chfirst) { /*matched first character*/
00320                 
00321                 register short ixpattern;
00322                 register char *p = pbuffer;
00323                 
00324                 for (ixpattern = 2; ixpattern <= lenpattern; ixpattern++) {
00325                     
00326                     if (p >= pbufferend) { /*ran out of chars in the buffer*/
00327                         
00328                         --ixpattern; /*make it the number of chars already matched*/
00329                         
00330                         backupfilepos (fnum, (long) ixpattern);
00331                         
00332                         fpos -= ixpattern;
00333                         
00334                         goto reloadbuffer;
00335                         }
00336                     
00337                     if (*p++ != pattern [ixpattern]) 
00338                         goto fastloop;
00339                     
00340                     } /*for*/
00341                 
00342                 *idx = fpos + (pbuffer - *hbuffer - 1);
00343                 
00344                 flreturned = true;
00345                 
00346                 goto exit;
00347                 } /*first character matched*/
00348             
00349             fastloop:
00350                 ;
00351             } /*for*/
00352         
00353         reloadbuffer:
00354         
00355         //unlockhandle (hbuffer);
00356         
00357         if (!loadbufferfromfile (fnum, hbuffer, &ctbytes))
00358             goto exit;
00359         
00360         if (ctbytes < lenpattern) { /*not enough chars to look at*/
00361             
00362             flreturned = false;
00363             
00364             goto exit;
00365             }
00366         
00367         fpos += oldctbytes; /*for computing returned value*/
00368         
00369         oldctbytes = ctbytes;
00370         } /*while*/
00371         
00372     exit:
00373     
00374     disposehandle (hbuffer);
00375     
00376     filecloser (hfile, fnum);
00377     
00378     return (flreturned);
00379     } /*fiffindinfile*/
00380     
00381     
00382 boolean fifcomparefiles (const tyfilespec *fs1, const tyfilespec *fs2) {
00383     
00384     /*
00385     compare the two files byte-by-byte and return true if they are exactly
00386     equal. only compares the data forks of the files.
00387     */
00388     
00389     hdlfilenum fnum1 = 0, fnum2 = 0;
00390     Handle hbuffer1 = nil, hbuffer2 = nil;
00391     long ctbytes1, ctbytes2;
00392     boolean flreturned = false;
00393     hdlopenfile hfile1, hfile2;
00394     
00395     if (!fileopener (fs1, &hfile1, &fnum1))
00396         goto exit;
00397     
00398     if (!fileopener (fs2, &hfile2, &fnum2))
00399         goto exit;
00400     
00401     if (!newclearhandle ((long) filebuffersize, &hbuffer1))
00402         goto exit;
00403     
00404     if (!newclearhandle ((long) filebuffersize, &hbuffer2))
00405         goto exit;
00406     
00407     while (true) {
00408         
00409         register long ix;
00410         register char *p1, *p2;
00411         
00412         if (!loadbufferfromfile (fnum1, hbuffer1, &ctbytes1))
00413             goto exit;
00414         
00415         if (!loadbufferfromfile (fnum2, hbuffer2, &ctbytes2))
00416             goto exit;
00417         
00418         if (ctbytes1 == 0) { 
00420             flreturned = ctbytes2 == 0; /*true if it's also empty*/
00421             
00422             goto exit;
00423             }
00424         
00425         if (ctbytes1 != ctbytes2) {
00426             
00427             flreturned = false;
00428             
00429             goto exit;
00430             }
00431         
00432         //lockhandle (hbuffer1);
00433         
00434         p1 = *hbuffer1; /*copy into register*/
00435         
00436         //lockhandle (hbuffer2);
00437         
00438         p2 = *hbuffer2; /*copy into register*/
00439         
00440         for (ix = 0; ix < ctbytes1; ix++) {
00441             
00442             if (*p1++ != *p2++) {
00443                 
00444                 flreturned = false;
00445                 
00446                 goto exit;
00447                 }
00448             } /*for*/
00449             
00450         //unlockhandle (hbuffer1);
00451         
00452         //unlockhandle (hbuffer2);
00453         } /*while*/
00454         
00455     exit:
00456     
00457     disposehandle (hbuffer1);
00458         
00459     disposehandle (hbuffer2);
00460         
00461     filecloser (hfile1, fnum1);
00462     
00463     filecloser (hfile2, fnum2);
00464     
00465     return (flreturned);
00466     } /*fifcomparefiles*/
00467     
00468 
00469 boolean fifcharcounter (const tyfilespec *fs, char chlookfor, long *count) {
00470     
00471     /*
00472     searches the indicated file for the character. count returns with the number 
00473     of matches. set chlookfor to (char) 13 to get the number of carriage returns
00474     or number of lines in the file.
00475     */
00476     
00477     register long ctmatches = 0;
00478     hdlfilenum fnum = 0;
00479     Handle hbuffer = nil;
00480     long ctbytes;
00481     boolean flreturned = false;
00482     hdlopenfile hfile = nil;
00483     
00484     if (!fileopener (fs, &hfile, &fnum))
00485         goto exit;
00486         
00487     if (!largefilebuffer (&hbuffer)) /*couldn't allocate minimum buffer*/
00488         goto exit;
00489         
00490     if (!loadbufferfromfile (fnum, hbuffer, &ctbytes))
00491         goto exit;
00492         
00493     if (ctbytes == 0) { /*it's an empty file*/
00494         
00495         flreturned = true;
00496         
00497         goto exit;
00498         }
00499         
00500     while (true) {
00501         
00502         register long ct = ctbytes;
00503         register long ix;
00504         register char *pbuffer;
00505         register char ch = chlookfor;
00506         
00507         //lockhandle (hbuffer);
00508         
00509         pbuffer = *hbuffer; /*copy into register*/
00510         
00511         for (ix = 0; ix < ct; ix++) {
00512             
00513             if (*pbuffer++ == ch) 
00514                 ctmatches++;
00515             } /*for*/
00516             
00517         //unlockhandle (hbuffer);
00518         
00519         if (!loadbufferfromfile (fnum, hbuffer, &ctbytes))
00520             goto exit;
00521             
00522         if (ctbytes == 0) { /*no more chars to look at*/
00523             
00524             flreturned = true;
00525             
00526             goto exit;
00527             }
00528         } /*while*/
00529         
00530     exit:
00531     
00532     *count = ctmatches;
00533     
00534     disposehandle (hbuffer);
00535         
00536     filecloser (hfile, fnum);
00537         
00538     return (flreturned);
00539     } /*fifcharcounter*/
00540     
00541 
00542 boolean fifclosefile (const tyfilespec *fs) {
00543     
00544     /*
00545     close the file indicated by fs. deallocate the record and buffer. close
00546     it if it wasn't open when openfile was called.
00547     */
00548     
00549     hdlopenfile hfile, hprev;
00550     register hdlopenfile hf;
00551     
00552     if (!findopenfile (fs, &hfile, &hprev)) { /*file isn't open*/
00553         
00554         fifopenfileerror (fs);
00555 
00556         return (false);
00557         }
00558     
00559     hf = hfile; /*copy into register*/
00560     
00561     closefile ((**hf).fnum);
00562     
00563     if (hprev == nil)
00564         hfirstfile = (**hf).nextfile;
00565     else
00566         (**hprev).nextfile = (**hf).nextfile;
00567         
00568     disposehandle ((**hf).hbuffer);
00569     
00570     disposehandle ((Handle) hf);
00571     
00572     return (true);
00573     } /*fifclosefile*/
00574 
00575 
00576 boolean fifcloseallfiles (long refcon) {
00577     
00578     register hdlopenfile x = hfirstfile;
00579     register hdlopenfile hnext;
00580     tyfilespec fs;
00581     
00582     while (x != nil) {
00583         
00584         hnext = (**x).nextfile;
00585         
00586         if ((**x).refcon == refcon) {
00587             
00588             fs = (**x).fs;
00589             
00590             fifclosefile (&fs);
00591             }
00592         
00593         x = hnext;
00594         } /*while*/
00595     
00596     return (true);
00597     } /*fifcloseallfiles*/
00598 
00599 
00600 boolean fifopenfile (const tyfilespec *fs, long refcon) {
00601     
00602     /*
00603     open the indicated file, allocating a record and linking it into the list.
00604     allocate a buffer. return true if the file could be opened.
00605     
00606     10/31/91 dmb: check for eof when file is first opened
00607     */
00608     
00609     hdlfilenum fnum;
00610     hdlopenfile hfile = nil;
00611     hdlopenfile hprev;
00612     register hdlopenfile hf;
00613     Handle hbuffer;
00614     long eof;
00615     
00616     if (findopenfile (fs, &hfile, &hprev)) /*file was already opened by us*/
00617         fifclosefile (fs);
00618     
00619     if (!fileopener (fs, &hfile, &fnum))
00620         return (false);
00621     
00622     if (!newclearhandle (sizeof (tyopenfile), (Handle *) &hfile))
00623         goto error;
00624         
00625     if (!newclearhandle ((long) filebuffersize, &hbuffer))
00626         goto error;
00627         
00628     hf = hfile; /*copy into register*/
00629     
00630     if (!filegeteof (fnum, &eof))
00631         goto error;
00632     
00633     (**hf).ctbytesleft = eof;
00634     
00635     (**hf).fnum = fnum;
00636     
00637     (**hf).fs = *fs;
00638     
00639     (**hf).nextfile = hfirstfile; /*insert at the head of the file list*/
00640     
00641     hfirstfile = hf;
00642     
00643     (**hf).hbuffer = hbuffer;
00644     
00645     (**hf).ixbuffer = filebuffersize; /*force file read on first getline/char*/
00646     
00647     (**hf).ctbufferbytes = filebuffersize; //do getposition will work
00648     
00649     (**hf).refcon = refcon;
00650     
00651     return (true);
00652     
00653     error:
00654     
00655     disposehandle ((**hfile).hbuffer);
00656     
00657     disposehandle ((Handle) hfile);
00658     
00659     return (false);
00660     } /*fifopenfile*/
00661     
00662     
00663 boolean fifendoffile (const tyfilespec *fs) {
00664     
00665     /*
00666     return true if there's no more info in the file to be read.
00667     */
00668     
00669     hdlopenfile h1, h2;
00670     
00671     if (!findopenfile (fs, &h1, &h2))
00672         return (true);
00673     
00674     return ((**h1).ctbytesleft <= 0);
00675     } /*fifendoffile*/
00676 
00677 
00678 static boolean fifread (const tyfilespec *fs, byte eolmarker, long ctmax, Handle *hdata) {
00679     
00680     /*
00681     read a chunk of data from the indicated file to a maximum of ctmax bytes.
00682     
00683     if eolmarker is non-zero, stop when a matching character is encountered.
00684     
00685     5.0.2b3 dmb: ignore actual value of eolmarker; it's either chnul or not. If not, 
00686     look for any kind of line ending.
00687     
00688     5.1.4 dmb: flstriplf handling gets smart about buffer boundaries.
00689     */
00690     
00691     register Handle *x = hdata;
00692     hdlopenfile hfile, hprev;
00693     register hdlopenfile hf;
00694     register long ctread = ctmax;
00695     byte ch;
00696     boolean flstriplf = false;
00697     
00698     *x = nil;
00699     
00700     if (!findopenfile (fs, &hfile, &hprev)) { /*file isn't open*/
00701         
00702         fifopenfileerror (fs);
00703 
00704         return (false);
00705         }
00706     
00707     hf = hfile; /*copy into register*/
00708     
00709     while (true) {
00710         
00711         register long ixbuffer = (**hf).ixbuffer;
00712         register long ixend = (**hf).ctbufferbytes;
00713         
00714         if (ixbuffer >= ixend) { /*ran out of chars in buffer*/
00715             
00716             if (!fileloadbuffer (hf)) {
00717                 
00718                 disposehandle (*x);
00719                 
00720                 *x = nil;
00721                 
00722                 return (false);
00723                 }
00724             
00725             ixbuffer = (**hf).ixbuffer;
00726             
00727             ixend = (**hf).ctbufferbytes;
00728             }
00729         
00730         /*
00731         first, see if first character is linefeed following previous cr
00732         */
00733         
00734         /*
00735         first, extract what we want out of current buffer
00736         */
00737         
00738         ctread -= ixend - ixbuffer; /*start by planning to read entire buffer*/
00739         
00740         if (ctread < 0) /*too many bytes; bring ixend in to match*/
00741             ixend += ctread;
00742         
00743         if (eolmarker != chnul) { /*see if eol is within range we're about to read*/
00744             
00745             register long ix;
00746             register byte *buf = (byte *) *(**hf).hbuffer;
00747             
00748             for (ix = ixbuffer; ix < ixend; ++ix) {
00749                 
00750                 ch = buf [ix];
00751                 
00752                 if (ch == chreturn || ch == chlinefeed) { /*found it*/
00753                     
00754                     if (ch == chreturn)
00755                         flstriplf = true;
00756                     
00757                     ixend = ix; /*shorten range*/
00758                     
00759                     ctread = 0; /*don't read no mo'*/
00760                     
00761                     break;
00762                     }
00763                 }
00764             }
00765         
00766         bundle { /*move the data*/
00767             
00768             register Handle buf = (**hf).hbuffer;
00769             register long ct = ixend - ixbuffer;
00770             
00771             if (*x == nil) { /*first time thru loop*/
00772                 
00773                 long ix = ixbuffer;
00774                 
00775                 if (!loadfromhandletohandle (buf, &ix, ct, false, x))
00776                     return (false);
00777                 }
00778             else {
00779                 
00780                 long ctbytes = gethandlesize (*x);
00781                 
00782                 if (!sethandlesize (*x, ctbytes + ct)) {
00783                     
00784                     disposehandle (*x);
00785                     
00786                     *x = nil;
00787                     
00788                     return (false);
00789                     }
00790                 
00791                 moveleft (*buf + ixbuffer, **x + ctbytes, ct);
00792                 }
00793             
00794             (**hf).ctbytesleft -= ct;
00795             }
00796         
00797         (**hf).ixbuffer = ixend; /*where we left off*/
00798         
00799         if (ctread <= 0) { /*we're done!*/
00800             
00801             if (eolmarker != chnul) { /*make sure we skip past the marker*/
00802                 
00803                 ++(**hf).ixbuffer;
00804                 
00805                 --(**hf).ctbytesleft;
00806                 
00807                 if (flstriplf) { // strip next character if it's a linefeed
00808                 
00809                     if (((**hf).ixbuffer < (**hf).ctbufferbytes) || fileloadbuffer (hf)) { // more chars
00810                     
00811                         if ((*(**hf).hbuffer) [(**hf).ixbuffer] == chlinefeed) {
00812                             
00813                             ++(**hf).ixbuffer;
00814                             
00815                             --(**hf).ctbytesleft;
00816                             }
00817                         }
00818                     }
00819                 }
00820             
00821             return (true);
00822             }
00823         
00824         /*
00825         buffer is now depleted; try to move on to next
00826         */
00827         
00828         if ((**hf).ctbytesleft <= 0) /*we've emptied last buffer*/
00829             return (true);
00830         } /*while*/
00831     } /*fifread*/
00832 
00833 
00834 
00835 boolean fifreadline (const tyfilespec *fs, Handle *linestring) {
00836     
00837     /*
00838     read a line of text from the indicated file.
00839     */
00840     
00841     return (fifread (fs, chreturn, longinfinity, linestring));
00842     } /*fifreadline*/
00843 
00844 
00845 boolean fifreadhandle (const tyfilespec *fs, long ctbytes, Handle *x) {
00846     
00847     /*
00848     read a chunk of data from the indicated file.
00849     */
00850     
00851     return (fifread (fs, chnul, ctbytes, x));
00852     } /*fifreadhandle*/
00853 
00854 
00855 boolean fifreadfile (const tyfilespec *fs, Handle *x) {
00856     
00857     /*
00858     read the whole file into memory and return the data to the caller.
00859     we assume that the file pointer is still at the beginning of the file,
00860     i.e. the file has just been opened but we haven't read from it yet.
00861     on success, caller is responsible for disposing the returned handle.
00862     
00863     2006-04-11 aradke: implemented for readwholefileverb in fileverbs.c
00864     */
00865 
00866     hdlopenfile hfile, hprev;
00867     long ctbytes;
00868     boolean fl;
00869     Handle h;
00870 
00871     *x = nil;
00872 
00873     if (!findopenfile (fs, &hfile, &hprev)) { /*file isn't open*/
00874         
00875         fifopenfileerror (fs);
00876 
00877         return (false);
00878         }
00879     
00880     if (!filegeteof ((**hfile).fnum, &ctbytes))
00881         return (false);
00882     
00883     if (!newhandle (ctbytes, &h))
00884         return (false);
00885     
00886     lockhandle (h);
00887     
00888     fl = fileread ((**hfile).fnum, ctbytes, *h);
00889     
00890     unlockhandle (h);
00891     
00892     if (fl) {
00893         *x = h;
00894         }
00895     else {
00896         disposehandle (h);
00897         }
00898     
00899     return (fl);
00900     } /*fifreadfile*/
00901 
00902 
00903 boolean fifwritehandle (const tyfilespec *fs, Handle x) {
00904     
00905     /*
00906     write some data at the end of the indicated file. it may be slow, but it's
00907     very easy to use! then again it might not be slow.
00908     */
00909     
00910     boolean fl;
00911     hdlopenfile hfile;
00912     hdlfilenum fnum;
00913     long ctbytes = gethandlesize (x);
00914     long eofPos;
00915     
00916     if (ctbytes == 0) /*nothing to write*/
00917         return (true);
00918     
00919     if (!fileopener (fs, &hfile, &fnum))
00920         return (false);
00921     
00922     filegeteof (fnum, &eofPos);
00923 
00924     filesetposition (fnum, eofPos); /*position at the end of the file*/
00925     
00926     fl = filewrite (fnum, ctbytes, *x); /*this call does not move memory*/
00927     
00928     filecloser (hfile, fnum);
00929     
00930     return (fl);
00931     } /*fifwritehandle*/
00932 
00933 
00934 boolean fifwriteline (const tyfilespec *fs, Handle linestring) {
00935     
00936     /*
00937     write a line at the end of the indicated file.
00938     */
00939     
00940     #ifdef WIN95VERSION
00941         byte bseol [] = "\002\r\n";
00942     #endif
00943     #ifdef MACVERSION
00944         byte bseol [] = "\001\r";
00945     #endif
00946     
00947     if (!pushtexthandle (bseol, linestring))
00948         return (false);
00949     
00950     return (fifwritehandle (fs, linestring));
00951     } /*fifwriteline*/
00952 
00953 
00954 boolean fifsetposition (const tyfilespec *fs, long pos) {
00955     
00956     /*
00957     5.0.1 dmb: new function. don't bother optimizing case where we're
00958     repositioning withing the current buffer. In most cases, we'll be
00959     called once, before any read operations.
00960     */
00961 
00962     hdlopenfile hfile, hprev;
00963     register hdlopenfile hf;
00964     long eof;
00965     
00966     if (!findopenfile (fs, &hfile, &hprev)) { /*file isn't open*/
00967         
00968         fifopenfileerror (fs);
00969 
00970         return (false);
00971         }
00972     
00973     hf = hfile; /*copy into register*/
00974     
00975     if (!filesetposition ((**hf).fnum, pos))
00976         return (false);
00977 
00978     if (filegeteof ((**hf).fnum, &eof))
00979         (**hf).ctbytesleft = eof - pos;
00980     
00981     (**hf).ixbuffer = filebuffersize; /*force file read on first getline/char*/
00982     
00983     (**hf).ctbufferbytes = filebuffersize; //so getposition will work
00984     
00985     return (true);
00986     } /*fifsetposition*/
00987 
00988 
00989 boolean fifgetposition (const tyfilespec *fs, long *pos) {
00990     
00991     /*
00992     5.0.1 dmb: new function
00993     
00994     5.1.5 dmb: account for unread buffer bytes
00995     */
00996 
00997     hdlopenfile hfile, hprev;
00998     register hdlopenfile hf;
00999     
01000     if (!findopenfile (fs, &hfile, &hprev)) { /*file isn't open*/
01001         
01002         fifopenfileerror (fs);
01003 
01004         return (false);
01005         }
01006     
01007     hf = hfile; /*copy into register*/
01008     
01009     if (!filegetposition ((**hf).fnum, pos)) // next read will go from current file pos
01010         return (false);
01011     
01012     *pos -= (**hf).ctbufferbytes - (**hf).ixbuffer; // virtual pos is within already-read buffer
01013     
01014     return (true);
01015     } /*fifgetposition*/
01016 
01017 
01018 boolean fifsetendoffile (const tyfilespec *fs, long eof) {
01019     
01020     /*
01021     set the eof for the file, opening & closing it if necessary
01022     
01023     5.0.1 dmb: reset ctbytesleft after changing the eof
01024     
01025     5.0.2 dmb: pin fpos after changing eof
01026     
01027     2003-05-26 AR: only update ctbytesleft and fpos if hfile is not nil.
01028     It can be nil if the file was not already open.
01029     */
01030     
01031     boolean fl;
01032     hdlopenfile hfile;
01033     hdlfilenum fnum;
01034     
01035     if (!fileopener (fs, &hfile, &fnum))
01036         return (false);
01037     
01038     fl = fileseteof (fnum, eof);
01039     
01040     if (fl && hfile != nil) {
01041         
01042         (**hfile).ctbytesleft = max (0, eof - (**hfile).fpos);
01043         
01044         (**hfile).fpos = min ((**hfile).fpos, eof);
01045         }
01046     
01047     filecloser (hfile, fnum);
01048     
01049     return (fl);
01050     } /*fifseteof*/
01051 
01052 
01053 boolean fifgetendoffile (const tyfilespec *fs, long *eof) {
01054     
01055     /*
01056     set the eof for the file, opening & closing it if necessary
01057     
01058     5.0.1 dmb: reset ctbytesleft after changing the eof
01059     */
01060     
01061     boolean fl;
01062     hdlopenfile hfile;
01063     hdlfilenum fnum;
01064     
01065     if (!fileopener (fs, &hfile, &fnum))
01066         return (false);
01067     
01068     fl = filegeteof (fnum, eof);
01069     
01070     filecloser (hfile, fnum);
01071     
01072     return (fl);
01073     } /*fifseteof*/
01074 
01075 
01076 
01077 
01078 

Generated on Wed May 31 18:19:47 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6