home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / apps.to.go / DTS.Lib / StringUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-07  |  15.0 KB  |  760 lines  |  [TEXT/MPS ]

  1. /*
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    Collection of String Utilities for DTS Sample code
  5. **
  6. **    File:        StringUtils.c
  7. **
  8. **    Copyright © 1988-1993 Apple Computer, Inc.
  9. **    All rights reserved.
  10. */
  11.  
  12. /* You may incorporate this sample code into your applications without
  13. ** restriction, though the sample code has been provided "AS IS" and the
  14. ** responsibility for its operation is 100% yours.  However, what you are
  15. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  16. ** after having made changes. If you're going to re-distribute the source,
  17. ** we require that you make it clear in the source that the code was
  18. ** descended from Apple Sample Code, but that you've made changes. */
  19.  
  20. #ifndef __MEMORY__
  21. #include <Memory.h>
  22. #endif
  23.  
  24. #ifndef __STRINGUTILS__
  25. #include "StringUtils.h"
  26. #endif
  27.  
  28.  
  29.  
  30. /* These functions should be linked into whatever segment holds main().  This will
  31. ** guarantee that the functions will always be in memory when called.  It is important
  32. ** that they are in memory, because if a pointer is passed in that points into an
  33. ** unlocked handle, the mere fact that the code needs to get loaded may cause the
  34. ** handle that is pointed into to move.  If you stick to these string functions,
  35. ** you will not have to worry about the handle moving when the string function is
  36. ** called.  If you have your own string functions, and you wish the same safety
  37. ** factor, link the string handling code into the same segment as main(), as you
  38. ** do with these string functions. */
  39.  
  40. static short    gBase;
  41. static Boolean    gHandleChars;
  42.  
  43.  
  44.  
  45. /*****************************************************************************/
  46. /*****************************************************************************/
  47. /*****************************************************************************/
  48.  
  49.  
  50.  
  51. /* Return the length of the c-string.  (Same as strlen, but this function isn't
  52. ** part of the string library.  The entire library may be more than you wish to
  53. ** link into the code segment that holds main, so this (and other) standard
  54. ** library function has been duplicated here. */
  55.  
  56. #pragma segment StringUtils
  57. short    clen(char *cptr)
  58. {
  59.     short    i;
  60.  
  61.     for (i = 0; cptr[i]; ++i) {};
  62.     return(i);
  63. }
  64.  
  65.  
  66.  
  67. /*****************************************************************************/
  68.  
  69.  
  70.  
  71. /* Catenate two c-strings. */
  72.  
  73. #pragma segment StringUtils
  74. char    *ccat(char *s1, char *s2)
  75. {
  76.     ccpy(s1 + clen(s1), s2);
  77.     return(s1);
  78. }
  79.  
  80.  
  81.  
  82. /*****************************************************************************/
  83.  
  84.  
  85.  
  86. /* Copy a c-string. */
  87.  
  88. #pragma segment StringUtils
  89. char    *ccpy(char *s1, char *s2)
  90. {
  91.     char    *c1, *c2;
  92.  
  93.     c1 = s1;
  94.     c2 = s2;
  95.     while ((*c1++ = *c2++) != 0) {};
  96.     return(s1);
  97. }
  98.  
  99.  
  100.  
  101. /*****************************************************************************/
  102.  
  103.  
  104.  
  105. /* Compare two pascal-strings. */
  106.  
  107. #pragma segment StringUtils
  108. short    pcmp(StringPtr s1, StringPtr s2)
  109. {
  110.     short    i, len;
  111.     char    j;
  112.  
  113.     if ((len = s1[0]) > s2[0]) len = s2[0];
  114.  
  115.     for (i = 1; i <= len; ++i) {
  116.         j = s1[i] - s2[i];
  117.         if (j) return(j);
  118.     }
  119.  
  120.     return(s1[0] - s2[0]);
  121. }
  122.  
  123.  
  124.  
  125. /*****************************************************************************/
  126.  
  127.  
  128.  
  129. /* Catenate two pascal-strings. */
  130.  
  131. #pragma segment StringUtils
  132. void    pcat(StringPtr d, StringPtr s)
  133. {
  134.     short    i, j;
  135.  
  136.     if (((j = s[0]) + d[0]) > 255)
  137.         j = 255 - d[0];
  138.             /* Limit dest string to 255. */
  139.  
  140.     for (i = 0; i < j;) d[++d[0]] = s[++i];
  141. }
  142.  
  143.  
  144.  
  145. /*****************************************************************************/
  146.  
  147.  
  148.  
  149. /* Copy a pascal-string. */
  150.  
  151. #pragma segment StringUtils
  152. void    pcpy(StringPtr d, StringPtr s)
  153. {
  154.     short    i;
  155.  
  156.     i = *s;
  157.     do {
  158.         d[i] = s[i];
  159.     } while (i--);
  160. }
  161.  
  162.  
  163.  
  164. /*****************************************************************************/
  165.  
  166.  
  167.  
  168. /* Convert a c-string to a pascal-string. */
  169.  
  170. #pragma segment StringUtils
  171. void    c2p(char *cptr)
  172. {
  173.     char    len;
  174.  
  175.     BlockMove(cptr, cptr + 1, len = clen(cptr));
  176.     *cptr = len;
  177. }
  178.  
  179.  
  180.  
  181. /*****************************************************************************/
  182.  
  183.  
  184.  
  185. /* Convert a pascal-string to a c-string. */
  186.  
  187. #pragma segment StringUtils
  188. void    p2c(StringPtr cptr)
  189. {
  190.     unsigned char    len;
  191.  
  192.     BlockMove(cptr + 1, cptr, len = *cptr);
  193.     cptr[len] = 0;
  194. }
  195.  
  196.  
  197.  
  198. /*****************************************************************************/
  199. /*****************************************************************************/
  200. /*****************************************************************************/
  201.  
  202.  
  203.  
  204. /* Catenate a single character multiple times onto the designated string. */
  205.  
  206. #pragma segment StringUtils
  207. void    ccatchr(char *cptr, char c, short count)
  208. {
  209.     ccpychr(cptr + clen(cptr), c, count);
  210. }
  211.  
  212.  
  213.  
  214. /*****************************************************************************/
  215.  
  216.  
  217.  
  218. /* Convert the value into text for the base-10 number and catenate it to
  219. ** the designated string.  The value is assumed to be signed.  If you wish
  220. ** to have an unsigned decimal value, call ccatnum with a base of 10. */
  221.  
  222. #pragma segment StringUtils
  223. void    ccatpaddec(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  224. {
  225.     ccatpadnum(cptr + clen(cptr), padChr, minApnd, maxApnd, v, -10);
  226.         /* Catenate value base 10, signed. */
  227. }
  228.  
  229. void    ccatdec(char *cptr, long v)
  230. {
  231.     ccatnum(cptr, v, -10);
  232. }
  233.  
  234.  
  235.  
  236. /*****************************************************************************/
  237.  
  238.  
  239.  
  240. /* Convert the value into text for base-16, format it, and catenate it to the
  241. ** designated string.  ccatnum could be used, since it handles multiple bases,
  242. ** but ccathex allows for additional common formatting and padding of the
  243. ** hex value. */
  244.  
  245. #pragma segment StringUtils
  246. void    ccatpadhex(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  247. {
  248.     char    str[33], *sptr;
  249.     short    len;
  250.  
  251.     cptr += clen(cptr);            /* We're appending, so point to the end of the string. */
  252.     ccpynum(str, v, 16);        /* Generate minimum-digit hex value. */
  253.  
  254.     if ((len = clen(sptr = str)) > maxApnd)
  255.         sptr = str + len - maxApnd;
  256.  
  257.     if ((len = clen(sptr)) < minApnd)
  258.         if (padChr)
  259.             ccatchr(cptr, padChr, (minApnd - len));
  260.                 /* if we have a pad character, and if necessary, pad the string. */
  261.  
  262.     ccat(cptr, sptr);            /* Add the hex digits to the string. */
  263. }
  264.  
  265. void    ccathex(char *cptr, long v)
  266. {
  267.     ccatpadhex(cptr, 0, 0, 8, v);
  268. }
  269.  
  270.  
  271.  
  272. /*****************************************************************************/
  273.  
  274.  
  275.  
  276. /* Convert the value into text for the designated base.  Catenate the text to
  277. ** the designated string. */
  278.  
  279. #pragma segment StringUtils
  280. void    ccatpadnum(char *cptr, char padChr, short minApnd, short maxApnd, long v, short base)
  281. {
  282.     ccpypadnum(cptr + clen(cptr), padChr, minApnd, maxApnd, v, base);
  283. }
  284.  
  285. void    ccatnum(char *cptr, long v, short base)
  286. {
  287.     ccpynum(cptr + clen(cptr), v, base);
  288. }
  289.  
  290.  
  291.  
  292. /*****************************************************************************/
  293.  
  294.  
  295.  
  296. #pragma segment StringUtils
  297. void    ccpychr(char *cptr, char c, short count)
  298. {
  299.     for (;count--; ++cptr) *cptr = c;
  300.     *cptr = 0;
  301. }
  302.  
  303.  
  304.  
  305. /*****************************************************************************/
  306.  
  307.  
  308.  
  309. #pragma segment StringUtils
  310. void    ccpypaddec(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  311. {
  312.     ccpypadnum(cptr, padChr, minApnd, maxApnd, v, -10);
  313. }
  314.  
  315. void    ccpydec(char *cptr, long v)
  316. {
  317.     ccpynum(cptr, v, -10);
  318. }
  319.  
  320.  
  321.  
  322. /*****************************************************************************/
  323.  
  324.  
  325.  
  326. #pragma segment StringUtils
  327. void    ccpypadhex(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  328. {
  329.     cptr[0] = 0;
  330.     ccatpadhex(cptr, padChr, minApnd, maxApnd, v);
  331. }
  332.  
  333. void    ccpyhex(char *cptr, long v)
  334. {
  335.     cptr[0] = 0;
  336.     ccathex(cptr, v);
  337. }
  338.  
  339.  
  340.  
  341. /*****************************************************************************/
  342.  
  343.  
  344.  
  345. #pragma segment StringUtils
  346. void    ccpypadnum(char *cptr, char padChr, short minApnd, short maxApnd, long v, short base)
  347. {
  348.     pcpypadnum((StringPtr)cptr, padChr, minApnd, maxApnd, v, base);
  349.     p2c((StringPtr)cptr);
  350. }
  351.  
  352. void    ccpynum(char *cptr, long v, short base)
  353. {
  354.     pcpynum((StringPtr)cptr, v, base);
  355.     p2c((StringPtr)cptr);
  356. }
  357.  
  358.  
  359.  
  360. /*****************************************************************************/
  361. /*****************************************************************************/
  362. /*****************************************************************************/
  363.  
  364.  
  365.  
  366. #pragma segment StringUtils
  367. long    c2dec(char *cptr, short *charsUsed)
  368. {
  369.     return(c2num(cptr, 10, charsUsed));
  370. }
  371.  
  372.  
  373.  
  374. /*****************************************************************************/
  375.  
  376.  
  377.  
  378. #pragma segment StringUtils
  379. long    c2hex(char *cptr, short *charsUsed)
  380. {
  381.     return(c2num(cptr, 16, charsUsed));
  382. }
  383.  
  384.  
  385.  
  386. /*****************************************************************************/
  387.  
  388.  
  389.  
  390. #pragma segment StringUtils
  391. long    c2num(char *cptr, short base, short *charsUsed)
  392. {
  393.     Boolean    firstDigit;
  394.     short    i, sgn;
  395.     short    c;
  396.     long    val;
  397.  
  398.     sgn = 1;
  399.     for (firstDigit = false, val = 0, i = 0;;) {
  400.         c = cptr[i++];
  401.         if (base == 256) {
  402.             if (!c) break;
  403.             if (c == '\'') {
  404.                 ++i;
  405.                 break;
  406.             }
  407.             val *= base;
  408.             val += c;
  409.             continue;
  410.         }
  411.         if (c == '-') {
  412.             if (firstDigit) break;
  413.             if (sgn == -1)  break;
  414.             sgn = -1;
  415.             continue;
  416.         }
  417.         if (c == '$') {
  418.             if (firstDigit) break;
  419.             base = 16;
  420.             continue;
  421.         }
  422.         if (gHandleChars) {
  423.             if (c == '\'') {
  424.                 if (firstDigit) break;
  425.                 base = 256;
  426.                 continue;
  427.             }
  428.         }
  429.         if ((!firstDigit) && (c == ' ')) continue;
  430.         c -= '0';
  431.         if (c > 16) c -= 7;        /* Make 'A' a 10, etc. */
  432.         if (c > 32) c -= 32;    /* Make lower-case upper-case. */
  433.         if (c < 0) break;
  434.         if (c >= base) break;
  435.         val *= base;
  436.         val += (c * sgn);
  437.         firstDigit = true;
  438.     }
  439.  
  440.     if (charsUsed) *charsUsed = --i;
  441.  
  442.     gBase = base;
  443.     return(val);
  444. }
  445.  
  446.  
  447.  
  448. /*****************************************************************************/
  449.  
  450.  
  451.  
  452. #pragma segment StringUtils
  453. short    GetLastBase(Boolean handleChars)
  454. {
  455.     gHandleChars = handleChars;
  456.     return(gBase);
  457. }
  458.  
  459.  
  460.  
  461. /*****************************************************************************/
  462. /*****************************************************************************/
  463. /*****************************************************************************/
  464.  
  465.  
  466.  
  467. /* Catenate a single character multiple times onto the designated string. */
  468.  
  469. #pragma segment StringUtils
  470. void    pcatchr(StringPtr pptr, char c, short count)
  471. {
  472.     while (count--) pptr[++(pptr[0])] = c;
  473. }
  474.  
  475.  
  476.  
  477. /*****************************************************************************/
  478.  
  479.  
  480.  
  481. #pragma segment StringUtils
  482. void    pcatpaddec(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  483. {
  484.     pcatpadnum(pptr, padChr, minApnd, maxApnd, v, -10);
  485. }
  486.  
  487. void    pcatdec(StringPtr pptr, long v)
  488. {
  489.     pcatnum(pptr, v, -10);
  490. }
  491.  
  492.  
  493.  
  494. /*****************************************************************************/
  495.  
  496.  
  497.  
  498. #pragma segment StringUtils
  499. void    pcatpadhex(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  500. {
  501.     char    str[33];
  502.  
  503.     ccpypadhex(str, padChr, minApnd, maxApnd, v);
  504.     c2p(str);
  505.     pcat(pptr, (StringPtr)str);
  506. }
  507.  
  508. void    pcathex(StringPtr pptr, long v)
  509. {
  510.     pcatpadhex(pptr, 0, 0, 8, v);
  511. }
  512.  
  513.  
  514.  
  515. /*****************************************************************************/
  516.  
  517.  
  518.  
  519. #pragma segment StringUtils
  520. long    pcatnum(StringPtr pptr, long v, short base)
  521. {
  522.     unsigned long    j, vv;
  523.  
  524.     vv = v;
  525.     if (base < 0) {
  526.         base = -base;
  527.         if (v < 0) {
  528.             pptr[++*pptr] = '-';
  529.             vv = -vv;
  530.         }
  531.     }
  532.     j = 0;
  533.     if (vv >= base)
  534.         j = pcatnum(pptr, vv / base, base);
  535.  
  536.     pptr[++*pptr] = "0123456789ABCDEF"[vv - j];
  537.     return(base * vv);
  538. }
  539.  
  540. void    pcatpadnum(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v, short base)
  541. {
  542.     Str32    str;
  543.  
  544.     pcpynum(str, v, base);        /* Generate minimum-digit hex value. */
  545.  
  546.     if (str[0] > maxApnd) str[0] = maxApnd;
  547.  
  548.     if (str[0] < minApnd)
  549.         if (padChr)
  550.             pcatchr(pptr, padChr, (minApnd - str[0]));
  551.                 /* if we have a pad character, and if necessary, pad the string. */
  552.  
  553.     pcat(pptr, str);            /* Add the hex digits to the string. */
  554. }
  555.  
  556.  
  557.  
  558. /*****************************************************************************/
  559.  
  560.  
  561.  
  562. #pragma segment StringUtils
  563. void    pcpychr(StringPtr pptr, char c, short count)
  564. {
  565.     pptr[0] = 0;
  566.     pcatchr(pptr, c, count);
  567. }
  568.  
  569.  
  570.  
  571. /*****************************************************************************/
  572.  
  573.  
  574.  
  575. #pragma segment StringUtils
  576. void    pcpypaddec(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  577. {
  578.     *pptr = 0;
  579.     pcatpaddec(pptr, padChr, minApnd, maxApnd, v);
  580. }
  581.  
  582. void    pcpydec(StringPtr pptr, long v)
  583. {
  584.     *pptr = 0;
  585.     pcatdec(pptr, v);
  586. }
  587.  
  588.  
  589.  
  590. /*****************************************************************************/
  591.  
  592.  
  593.  
  594. #pragma segment StringUtils
  595. void    pcpypadnum(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v, short base)
  596. {
  597.     *pptr = 0;
  598.     pcatpadnum(pptr, padChr, minApnd, maxApnd, v, base);
  599. }
  600.  
  601. void    pcpynum(StringPtr pptr, long v, short base)
  602. {
  603.     *pptr = 0;
  604.     pcatnum(pptr, v, base);
  605. }
  606.  
  607.  
  608.  
  609. /*****************************************************************************/
  610.  
  611.  
  612.  
  613. #pragma segment StringUtils
  614. void    pcpypadhex(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  615. {
  616.     *pptr = 0;
  617.     pcatpadhex(pptr, padChr, minApnd, maxApnd, v);
  618. }
  619.  
  620. void    pcpyhex(StringPtr pptr, long v)
  621. {
  622.     pcpypadhex(pptr, 0, 0, 8, v);
  623. }
  624.  
  625.  
  626.  
  627. /*****************************************************************************/
  628.  
  629.  
  630.  
  631. #pragma segment StringUtils
  632. long    p2dec(StringPtr pptr, short *charsUsed)
  633. {
  634.     return(p2num(pptr, 10, charsUsed));
  635. }
  636.  
  637.  
  638.  
  639. /*****************************************************************************/
  640.  
  641.  
  642.  
  643. #pragma segment StringUtils
  644. long    p2hex(StringPtr pptr, short *charsUsed)
  645. {
  646.     return(p2num(pptr, 16, charsUsed));
  647. }
  648.  
  649.  
  650.  
  651. /*****************************************************************************/
  652.  
  653.  
  654.  
  655. #pragma segment StringUtils
  656. long    p2num(StringPtr pptr, short base, short *charsUsed)
  657. {
  658.     long    val;
  659.  
  660.     p2c(pptr);
  661.     val = c2num((char *)pptr, base, charsUsed);
  662.     c2p((char *)pptr);
  663.     return(val);
  664. }
  665.  
  666.  
  667.  
  668. /*****************************************************************************/
  669. /*****************************************************************************/
  670. /*****************************************************************************/
  671.  
  672.  
  673.  
  674. #pragma segment StringUtils
  675. short    GetHexByte(char *cptr)
  676. {
  677.     short    val, i, chr;
  678.  
  679.     for (val = 0, i = 0; i < 2; ++i) {
  680.         chr = cptr[i];
  681.         if (chr == '=') return(cptr[++i]);
  682.         if (chr == '≈') {
  683.             chr = cptr[++i];
  684.             if ((chr >= 'a') && (chr <= 'z')) chr -= 32;
  685.             return(chr);
  686.         }
  687.         if (chr > 'F')
  688.             chr -= 0x20;
  689.         if (chr > '9')
  690.             chr -= ('A' - '9' - 1);
  691.         val = (val << 4) + chr - '0';
  692.     }
  693.     return(val);
  694. }
  695.  
  696.  
  697.  
  698. /*****************************************************************************/
  699.  
  700.  
  701.  
  702. #pragma segment StringUtils
  703. Boolean    EqualHandle(void *h1, void *h2)
  704. {
  705.     long    s1, s2;
  706.     Ptr        p1, p2;
  707.  
  708.     if ((h1) && (!h2)) return(false);
  709.     if ((h2) && (!h1)) return(false);
  710.     if ((s1 = GetHandleSize(h1)) != (s2 = GetHandleSize(h2))) return(false);
  711.  
  712.     p1 = *(Handle)h1;
  713.     p2 = *(Handle)h2;
  714.     for (s1 = 0; s1 < s2; ++s1)
  715.         if (p1[s1] != p2[s1]) return(false);
  716.         
  717.     return(true);
  718. }
  719.  
  720.  
  721.  
  722. /*****************************************************************************/
  723.  
  724.  
  725.  
  726. #pragma segment StringUtils
  727. Boolean    EqualData(void *v1, void *v2, long size)
  728. {
  729.     Ptr        p1, p2;
  730.     long    ii;
  731.  
  732.     if ((v1) && (!v2)) return(false);
  733.     if ((v2) && (!v1)) return(false);
  734.  
  735.     p1 = (Ptr)v1;
  736.     p2 = (Ptr)v2;
  737.     for (ii = 0; ii < size; ++ii)
  738.         if (p1[ii] != p2[ii]) return(false);
  739.         
  740.     return(true);
  741. }
  742.  
  743.  
  744.  
  745. /*****************************************************************************/
  746.  
  747.  
  748.  
  749. #pragma segment StringUtils
  750. void    SetMem(void *vptr, unsigned char c, unsigned long len)
  751. {
  752.     Ptr    ptr;
  753.  
  754.     ptr = (Ptr)vptr;
  755.     while (len--) *ptr++ = c;
  756. }
  757.  
  758.  
  759.  
  760.