appletmemory.c

Go to the documentation of this file.
00001 
00002 /*  $Id: appletmemory.c 355 2005-01-11 22:48:55Z andreradke $    */
00003 
00004 /*© copyright 1991-96 UserLand Software, Inc. All Rights Reserved.*/
00005 
00006 
00007 #include "appletdefs.h"
00008 #include "appletmemory.h"
00009 #include "appletstrings.h"
00010 #include "appletsyserror.h"
00011 
00012 
00013 boolean usetempmemory = false; /*can be set externally to force allocations into temporary memory*/
00014 
00015 
00016 
00017 
00018 void moveleft (void *psource, void *pdest, long length) {
00019     
00020     /*
00021     do a mass memory move with the left edge leading.  good for closing
00022     up a gap in a buffer, among other thingsÉ
00023     */
00024     
00025     char *ps, *pd;
00026     long ctloops;
00027     
00028     ctloops = length;
00029     
00030     if (ctloops > 0) {
00031     
00032         ps = psource; /*copy into a register*/
00033     
00034         pd = pdest; /*copy into a register*/
00035     
00036         while (ctloops--) *pd++ = *ps++;
00037         }
00038     } /*moveleft*/
00039     
00040     
00041 void moveright (void *psource, void *pdest, long length) {
00042     
00043     /*
00044     do a mass memory move with the right edge leading.  good for opening
00045     up a gap in a buffer, among other thingsÉ
00046     */
00047     
00048     char *ps, *pd;
00049     long ctloops;
00050     
00051     ctloops = length;
00052     
00053     if (ctloops > 0) {
00054     
00055         ps = (char *) psource + length - 1; /*right edge of source*/
00056     
00057         pd = (char *) pdest + length - 1; /*right edge of destination*/
00058     
00059         while (ctloops--) *pd-- = *ps--;
00060         }
00061     } /*moveright*/
00062     
00063     
00064 boolean equalmemory (void *v1, void *v2, long ct) { 
00065     
00066     /*
00067     return true if the bytes are identical. useful for comparing records,
00068     remember to clearbyte them before copying data into the records.
00069     garbage bytes can make this test return false, when logically the
00070     records contain the same information.
00071     */
00072     
00073     char *p1 = (char *) v1;
00074     char *p2 = (char *) v2;
00075     
00076     if (ct <= 0)
00077         return (true);
00078         
00079     while (ct--) 
00080         if (*p1++ != *p2++)
00081             return (false);
00082         
00083     return (true);
00084     } /*equalmemory*/
00085     
00086 
00087 boolean equalhandles (Handle h1, Handle h2) {
00088     
00089     unsigned long len;
00090     
00091     if (h1 == nil)
00092         return (h2 == nil);
00093         
00094     if (h2 == nil)
00095         return (false);
00096         
00097     len = GetHandleSize (h1);
00098     
00099     if (GetHandleSize (h2) != len)
00100         return (false);
00101         
00102     return (equalmemory (*h1, *h2, len));
00103     } /*equalhandles*/
00104     
00105     
00106 void fillchar (void *pfill, long ctfill, char chfill) {
00107     
00108     /*
00109     do a mass memory fill -- copy ctfill chfills at pfill.
00110     */
00111     
00112     char *p = pfill;
00113     long ct = ctfill;
00114     char ch = chfill;
00115     
00116     assert (ct >= 0);
00117     
00118     while (ct--) *p++ = (char) ch; /*tight loop*/
00119     } /*fillchar*/
00120     
00121 
00122 void clearbytes (void *pclear, long ctclear) {
00123     
00124     /*
00125     fill memory with 0's.
00126     */
00127     
00128     fillchar (pclear, ctclear, (char) 0);
00129     } /*clearbytes*/
00130     
00131 
00132 void disposehandle (Handle h) {
00133     
00134     /*
00135     our own bottleneck for this built-in.  we don't require type coercion
00136     and we check if its nil.
00137     */
00138     
00139     if (h != nil)
00140         DisposHandle (h);
00141     } /*disposehandle*/
00142     
00143     
00144 long gethandlesize (Handle h) {
00145     
00146     if (h == nil)
00147         return (0);
00148         
00149     return (GetHandleSize (h));
00150     } /*gethandlesize*/
00151     
00152     
00153 boolean sethandlesize (Handle h, long size) {
00154     
00155     SetHandleSize (h, size);
00156     
00157     return (MemError () == noErr);
00158     } /*gethandlesize*/
00159     
00160     
00161 boolean getnewhandle (unsigned long ctbytes, Handle *h) {
00162     
00163     boolean fl;
00164     
00165     if (usetempmemory) {
00166         
00167         OSErr ec;
00168         
00169         *h = TempNewHandle (ctbytes, &ec);
00170         
00171         fl = ec == noErr;
00172         }
00173     else {
00174         *h = NewHandle (ctbytes);
00175         
00176         fl = *h != nil;
00177         }
00178         
00179     if (!fl)
00180         sysmemoryerror ();
00181         
00182     return (fl);
00183     } /*getnewhandle*/
00184     
00185     
00186 boolean newemptyhandle (Handle *h) {
00187     
00188     return (getnewhandle (0, h));
00189     } /*newemptyhandle*/
00190     
00191     
00192 Handle appnewhandle (Size ctbytes) {
00193     
00194     /*
00195     this api is designed to easily replace calls to NewHandle.
00196     */
00197     
00198     Handle h;
00199     
00200     if (!getnewhandle (ctbytes, &h))
00201         return (nil);
00202         
00203     return (h);
00204     } /*appnewhandle*/
00205     
00206     
00207 unsigned long memavail (void) {
00208     
00209     if (usetempmemory) 
00210         return (TempFreeMem ());
00211         
00212     return (FreeMem ());
00213     } /*memavail*/
00214     
00215     
00216 boolean copyhandle (Handle horig, Handle *hcopy) {
00217     
00218     unsigned long ctbytes;
00219     
00220     if (horig == nil) {
00221         
00222         *hcopy = nil;
00223         
00224         return (true);
00225         }
00226     
00227     ctbytes = GetHandleSize (horig);
00228     
00229     if (!getnewhandle (ctbytes, hcopy))
00230         return (false);
00231     
00232     moveleft (*horig, **hcopy, ctbytes);
00233     
00234     return (true);
00235     } /*copyhandle*/
00236     
00237 
00238 boolean enlargehandle (Handle hgrow, long ctgrow, void *newdata) {
00239     
00240     /*
00241     make the handle big enough to hold the new data, and move the new data in
00242     at the end of the newly enlarged handle.
00243     
00244     8/23/94 DW: check if ctgrow <= 0, drive defensively.
00245     */
00246     
00247     Handle h = hgrow;
00248     long ct = ctgrow;
00249     ptrchar p = newdata;
00250     long origsize;
00251     
00252     if (ctgrow <= 0) /*defensive driving*/
00253         return (true);
00254     
00255     origsize = gethandlesize (h);
00256     
00257     sethandlesize (h, origsize + ct);
00258         
00259     if (MemError () != noErr)
00260         return (false);
00261         
00262     moveleft (p, *h + origsize, ct);
00263     
00264     return (true);
00265     } /*enlargehandle*/ 
00266     
00267     
00268 boolean pushathandlestart (ptrvoid pdata, long ctbytes, Handle h) {
00269     
00270     unsigned long origsize = gethandlesize (h);
00271     
00272     if (!sethandlesize (h, origsize + ctbytes))
00273         return (false);
00274     
00275     moveright (*h, *h + ctbytes, origsize);
00276     
00277     moveleft (pdata, *h, ctbytes);
00278     
00279     return (true);
00280     } /*pushathandlestart*/
00281     
00282     
00283 boolean loadfromhandle (Handle hload, long *ixload, long ctload, void *pdata) {
00284     
00285     /*
00286     copy the next ctload bytes from hload into pdata and increment the index.
00287     
00288     return false if there aren't enough bytes.
00289     
00290     start ixload at 0.
00291     */
00292     
00293     Handle h = hload;
00294     ptrchar p = pdata;
00295     long ct = ctload;
00296     long ix = *ixload;
00297     long size;
00298     
00299     size = gethandlesize (h);
00300     
00301     if ((ix + ct) > size) /*asked for more bytes than there are*/
00302         return (false); 
00303         
00304     moveleft (*h + ix, p, ct); /*copy out of the handle*/
00305     
00306     *ixload = ix + ct; /*increment the index into the handle*/
00307     
00308     return (true);
00309     } /*loadfromhandle*/
00310     
00311 
00312 boolean loadhandlefromhandle (Handle hsource, long *ixsource, long ct, Handle *hdest) {
00313     
00314     boolean fl;
00315     
00316     fl = newfilledhandle (&(*hsource) [*ixsource], ct, hdest);
00317     
00318     *ixsource += ct;
00319     
00320     return (fl);
00321     } /*loadhandlefromhandle*/
00322 
00323 
00324 #define newstringlength(bs) ((unsigned char) (bs [0]))
00325 
00326 
00327 boolean newtexthandle (void *pstring, Handle *htext) {
00328     
00329     /*
00330     create a new handle to hold the text of the string.
00331     
00332     if the string is "\pABC" -- you get a handle of size 3.
00333     
00334     DW 1/21/95: ooops -- this guy couldn't handle strings 
00335     that are longer than 128 characters. yow. gotta change
00336     the definition of stringlength.
00337     */
00338     
00339     char *bs = (char *) pstring;
00340     unsigned long len;
00341     
00342     len = newstringlength (bs);
00343     
00344     if (!getnewhandle (len, htext))
00345         return (false);
00346         
00347     if (len > 0)
00348         moveleft (&bs [1], **htext, len);
00349     
00350     return (true);
00351     } /*newtexthandle*/
00352 
00353 
00354 boolean pushtexthandle (void *pstring, Handle htext) {
00355     
00356     /*
00357     htext is a handle created with newtexthandle.
00358     
00359     increase the size of the handle so we can push the text of bs at 
00360     the end of the handle (not including length byte).
00361     */
00362     
00363     unsigned char *bs = (unsigned char *) pstring;
00364     
00365     return (enlargehandle (htext, (unsigned long) stringlength (bs), (ptrchar) bs + 1));
00366     } /*pushtexthandle*/
00367 
00368 
00369 boolean pushhandleonhandle (Handle hsource, Handle hdest) {
00370     
00371     boolean fl;
00372     
00373     if (hsource == nil)
00374         return (true);
00375     
00376     lockhandle (hsource);
00377     
00378     fl = enlargehandle (hdest, gethandlesize (hsource), *hsource);
00379     
00380     unlockhandle (hsource);
00381     
00382     return (fl);
00383     } /*pushhandleonhandle*/
00384 
00385 
00386 void texthandletostring (Handle htext, void *pstring) {
00387     
00388     char *bs = (char *) pstring;
00389     long len;
00390     
00391     if (htext == nil) {
00392         
00393         setstringlength (bs, 0);
00394         
00395         return;
00396         }
00397     
00398     len = gethandlesize (htext);
00399     
00400     if (len > lenbigstring)
00401         len = lenbigstring;
00402     
00403     setstringlength (bs, len);
00404     
00405     moveleft (*htext, &bs [1], len);
00406     } /*texthandletostring*/
00407     
00408     
00409 boolean numbertotexthandle (long num, Handle *htext) {
00410     
00411     bigstring bs;
00412     
00413     NumToString (num, bs);
00414     
00415     return (newtexthandle (bs, htext));
00416     } /*numbertotexthandle*/
00417     
00418     
00419 void texthandletonumber (Handle htext, long *num, boolean *flerror) {
00420     
00421     bigstring bs;
00422     
00423     texthandletostring (htext, bs);
00424     
00425     stringtonumber (bs, num, flerror);
00426     } /*texthandletonumber*/
00427     
00428     
00429 void lockhandle (Handle h) {
00430     
00431     if (h != nil)
00432         HLock (h);
00433     } /*lockhandle*/
00434     
00435     
00436 void unlockhandle (Handle h) {
00437     
00438     if (h != nil)
00439         HUnlock (h);
00440     } /*unlockhandle*/
00441     
00442     
00443 boolean newclearhandle (long ctbytes, Handle *hnew) {
00444     
00445     if (!getnewhandle (ctbytes, hnew))
00446         return (false);
00447             
00448     clearbytes (**hnew, ctbytes);
00449     
00450     return (true);
00451     } /*newclearhandle*/
00452     
00453     
00454 boolean newfilledhandle (ptrvoid pdata, long ctbytes, Handle *hnew) {
00455     
00456     if (!getnewhandle (ctbytes, hnew))
00457         return (false);
00458             
00459     moveleft (pdata, **hnew, ctbytes);
00460     
00461     return (true);
00462     } /*newfilledhandle*/
00463     
00464     
00465 boolean newheapstring (ptrstring bs, hdlstring *hstring) {
00466 
00467     return (newfilledhandle (bs, (long) stringlength (bs) + 1, (Handle *) hstring));
00468     } /*newheapstring*/
00469     
00470     
00471 void copyheapstring (hdlstring hstring, void *bs) {
00472     
00473     if (hstring == nil) {
00474         
00475         ((char *) bs) [0] = 0;
00476         
00477         return;
00478         }
00479     
00480     lockhandle ((Handle) hstring);
00481     
00482     copystring (*hstring, bs);
00483     
00484     unlockhandle ((Handle) hstring);
00485     } /*copyheapstring*/
00486     
00487 
00488 boolean sethandlecontents (void *p, long ct, Handle h) {
00489 
00490     sethandlesize (h, ct);
00491     
00492     if (MemError () != noErr)
00493         return (false);
00494     
00495     moveleft (p, *h, ct);
00496     
00497     return (true);
00498     } /*sethandlecontents*/
00499 
00500 
00501 boolean minhandlesize (Handle h, long size) {
00502     
00503     if (gethandlesize (h) >= size) /*already big enough*/
00504         return (true);
00505         
00506     sethandlesize (h, size); /*try to make it larger*/
00507     
00508     return (MemError () == noErr);
00509     } /*minhandlesize*/
00510     
00511     
00512 boolean newintarray (short ct, hdlintarray *harray) {
00513     
00514     Handle h;
00515     
00516     if (!newclearhandle (longsizeof (short) * ct, &h))
00517         return (false);
00518         
00519     *harray = (hdlintarray) h;
00520     
00521     return (true);
00522     } /*newintarray*/
00523     
00524 
00525 boolean setintarray (hdlintarray harray, short ix, short val) {
00526     
00527     /*
00528     assign into a cell in a variable-size array of integers, 0-based index.
00529     
00530     return false if the array needed to be extended but there isn't enough
00531     memory to do it.
00532     */
00533     
00534     hdlintarray h = harray;
00535 
00536     if (!minhandlesize ((Handle) h, (ix + 1) * longsizeof (short)))
00537         return (false);
00538     
00539     (*harray) [ix] = val;
00540     
00541     return (true);
00542     } /*setintarray*/
00543     
00544     
00545 boolean getintarray (hdlintarray harray, short ix, short *val) {
00546     
00547     *val = (*harray) [ix];
00548     
00549     return (true);
00550     } /*getintarray*/
00551     
00552     
00553 void fillintarray (hdlintarray harray, short val) {
00554     
00555     hdlintarray h = harray;
00556     short x = val;
00557     short ct;
00558     
00559     ct = gethandlesize ((Handle) h) / longsizeof (short);
00560 
00561     while (--ct >= 0)
00562         (*h) [ct] = x;
00563     } /*fillintarray*/
00564 
00565 
00566 boolean testheapspace (long size) {
00567     
00568     /*
00569     see if there's enough space in the heap to allocate a handle of the given size.
00570     
00571     if not, generate an error, and return false.
00572     */
00573     
00574     Handle htest;
00575     
00576     htest = appnewhandle (size);
00577     
00578     if (htest == nil) 
00579         return (false);
00580     
00581     DisposHandle (htest);
00582     
00583     return (true);
00584     } /*testheapspace*/
00585 
00586 
00587 boolean popfromhandle (Handle hpop, long ctpop, ptrvoid pdata) {
00588     
00589     Handle h = hpop;
00590     long ixpop = gethandlesize (h) - ctpop;
00591     
00592     if (ixpop < 0)
00593         return (false);
00594     
00595     if (pdata != nil)
00596         moveleft (*h + ixpop, pdata, ctpop); /*copy out of the handle*/
00597     
00598     return (sethandlesize (h, ixpop)); /*should never fail -- getting smaller*/
00599     } /*popfromhandle*/
00600 
00601 
00602 boolean insertinhandle (bigstring bs, Handle h, unsigned long ix) {
00603     
00604     short stringlen = stringlength (bs);
00605     unsigned long ct = gethandlesize (h);
00606     unsigned long newlen = ct + stringlen;
00607     
00608     if (!sethandlesize (h, newlen))
00609         return (false);
00610     
00611     moveright (&(*h) [ix], &(*h) [ix + stringlen], ct - ix);
00612     
00613     moveleft (&bs [1], &(*h) [ix], stringlen);
00614     
00615     return (true);
00616     } /*insertinhandle*/
00617     
00618     
00619 boolean inserthandleinhandle (Handle hinsert, Handle h, unsigned long ix) {
00620     
00621     unsigned long insertlen = gethandlesize (hinsert);
00622     unsigned long ct = gethandlesize (h);
00623     unsigned long newlen = ct + insertlen;
00624     
00625     if (hinsert == nil) /*nothing to do*/
00626         return (true);
00627         
00628     if (!sethandlesize (h, newlen))
00629         return (false);
00630     
00631     moveright (&(*h) [ix], &(*h) [ix + insertlen], ct - ix);
00632     
00633     moveleft (*hinsert, &(*h) [ix], insertlen);
00634     
00635     return (true);
00636     } /*inserthandleinhandle*/
00637     
00638     
00639 void deleteinhandle (Handle h, unsigned long ix, unsigned long ctdelete) {
00640     
00641     unsigned long origct = gethandlesize (h);
00642     unsigned long ct = origct - ctdelete;
00643     
00644     moveleft (&(*h) [ix + ctdelete], &(*h) [ix], ct - ix);
00645     
00646     sethandlesize (h, ct);
00647     } /*deleteinhandle*/
00648     
00649     
00650 static unsigned char lowerchar (unsigned char ch) {
00651     
00652     if ((ch >= 'A') && (ch <= 'Z'))
00653         return (ch + 32);
00654     
00655     return (ch);
00656     } 
00659 boolean handlesearch (Handle h, bigstring searchfor, boolean flunicase, unsigned long *ix) {
00660     
00661     unsigned long ct, i, j;
00662     unsigned char ch, chfirst;
00663     unsigned long remainingchars;
00664     short lensearchfor = stringlength (searchfor);
00665     bigstring bscopy;
00666     
00667     if (lensearchfor == 0) /*defensive driving*/
00668         return (false);
00669         
00670     copystring (searchfor, bscopy);
00671     
00672     if (flunicase)
00673         alllower (bscopy);
00674     
00675     chfirst = bscopy [1];
00676     
00677     ct = gethandlesize (h);
00678     
00679     for (i = *ix; i < ct; i++) {
00680         
00681         ch = (*h) [i];
00682         
00683         if (flunicase)
00684             ch = lowerchar (ch);
00685         
00686         remainingchars = ct - i - 1;
00687         
00688         if (remainingchars < lensearchfor)
00689             break;
00690         
00691         if (ch == chfirst) {
00692             
00693             boolean flmatch = true;
00694             
00695             for (j = 2; j <= lensearchfor; j++) {
00696                 
00697                 ch = (*h) [i + j - 1];
00698                 
00699                 if (flunicase)
00700                     ch = lowerchar (ch);
00701                     
00702                 if (ch != bscopy [j]) {
00703                     
00704                     flmatch = false;
00705                     
00706                     break;
00707                     }
00708                 } /*for*/
00709                 
00710             if (flmatch) {
00711                 
00712                 *ix = i;
00713                 
00714                 return (true);
00715                 }
00716             }
00717         } /*for*/
00718     
00719     return (false);
00720     } /*handlesearch*/
00721     
00722     
00723 boolean handlereplaceall (Handle h, bigstring searchfor, Handle replacewith) {
00724     
00725     unsigned long ct, i, j;
00726     unsigned char ch, chfirst;
00727     unsigned long remainingchars;
00728     short lensearchfor = stringlength (searchfor);
00729     
00730     if (lensearchfor == 0) /*defensive driving*/
00731         return (true);
00732     
00733     chfirst = searchfor [1];
00734     
00735     ct = gethandlesize (h);
00736     
00737     for (i = 0; i < ct; i++) {
00738         
00739         ch = (*h) [i];
00740         
00741         remainingchars = ct - i - 1;
00742         
00743         if (remainingchars < lensearchfor)
00744             break;
00745         
00746         if (ch == chfirst) {
00747             
00748             boolean flmatch = true;
00749             
00750             for (j = 2; j <= lensearchfor; j++) {
00751                 
00752                 if ((*h) [i + j - 1] != searchfor [j]) {
00753                     
00754                     flmatch = false;
00755                     
00756                     break;
00757                     }
00758                 } /*for*/
00759                 
00760             if (flmatch) {
00761                 
00762                 deleteinhandle (h, i, lensearchfor);
00763                 
00764                 if (!inserthandleinhandle (replacewith, h, i))
00765                     return (false);
00766                     
00767                 i += gethandlesize (replacewith);
00768                 
00769                 ct = gethandlesize (h);
00770                 }
00771             }
00772         } /*for*/
00773     
00774     return (true);
00775     } /*handlereplaceall*/
00776     
00777     
00778 boolean getstringfromhandle (Handle h, unsigned long ixstart, unsigned long ixend, bigstring bs) {
00779     
00780     long ixload = ixstart;
00781     unsigned long len;
00782     
00783     len = ixend - ixstart + 1;
00784     
00785     if (len > lenbigstring)
00786         return (false);
00787     
00788     if (!loadfromhandle (h, &ixload, len, &bs [1]))
00789         return (false);
00790     
00791     setstringlength (bs, len);
00792     
00793     return (true);
00794     } /*getstringfromhandle*/
00795     
00796 
00797 long handlepatternmatch (void *ppattern, Handle pstringh) {
00798     
00799     unsigned char *bspattern = (unsigned char *) ppattern;
00800     unsigned long lenpattern = stringlength (bspattern);
00801     StringPtr   bs = (StringPtr)(*pstringh);
00802     unsigned long lenstring = GetHandleSize(pstringh);
00803     unsigned long i, ix, ixstring = 1;
00804     byte chfirst;
00805     
00806     if ((lenstring == 0) || (lenpattern == 0))
00807         return (0);
00808     
00809     chfirst = bspattern [1];
00810     
00811     while (true) {
00812         
00813         if (bs [ixstring] == chfirst) { /*matched at least first character in string*/
00814             
00815             for (i = 2; i <= lenpattern; i++) {
00816                 
00817                 ix = ixstring + i - 1;
00818                 
00819                 if (ix > lenstring) /*gone off end of string, can't match*/
00820                     return (0);
00821                 
00822                 if (bs [ix] != bspattern [i]) 
00823                     goto L1;
00824                 } /*for*/
00825             
00826             return (ixstring); /*loop terminated, full match*/
00827             }
00828         
00829         L1: /*advance to next character in string*/
00830         
00831         if (++ixstring > lenstring) /*reached end of string, not found*/
00832             return (0);
00833         } /*while*/
00834     } /*patternmatch*/
00835 

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