home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / os2prgc.zip / str.c < prev    next >
C/C++ Source or Header  |  1995-03-06  |  19KB  |  830 lines

  1. /*****************************************************************************
  2.  
  3.   STR.C -- Sample code for string and character type handling.
  4.   Copyright (C) 1993,94,95 by Craig Morrison, All Rights Reserved.
  5.  
  6.   You may use this code in your own projects, regardless of renumeration.
  7.   All I ask is that you prominently display the above copyright notice.
  8.  
  9.   Should you need assistance, I can be contacted at the following addresses:
  10.  
  11.         Fidonet:        Craig Morrison, 1:201/60@fidonet.org
  12.         Internet:       cam@wpc.cioe.com
  13.         Post:           Craig Morrison
  14.                         1316 Ferry St.
  15.                         Lafayette, IN 47901-1533
  16.                         USA
  17.  
  18.   NOTES:
  19.  
  20.     You'll notice the complete lack of any references to run-time
  21.     library functions. This was done on purpose so that *I* could
  22.     control what happens when a thread gets killed. This package
  23.     contains just about everything you'll need to do comm port/file
  24.     I/O, string manipulation and ordinal number conversions.
  25.  
  26.     This module provides the character type and string manipulation
  27.     functions.
  28.  
  29.  *****************************************************************************/
  30. #include <stdio.h>
  31.  
  32. /*****************************************************************************
  33.  
  34.   Converts 'a...z' to 'A...Z'
  35.  
  36.  *****************************************************************************/
  37. char cupper(char c)
  38. {
  39.     if ((c>=97) && (c<=122))
  40.         c &= ~32;
  41.  
  42.     return(c);
  43. }
  44.  
  45. /*****************************************************************************
  46.  
  47.   Converts 'A...Z' to 'a...z'
  48.  
  49.  *****************************************************************************/
  50. char clower(char c)
  51. {
  52.     if ((c>=65) && (c<=90))
  53.         c |= 32;
  54.  
  55.     return(c);
  56. }
  57.  
  58. /*****************************************************************************
  59.  
  60.   Copies src to dest.
  61.  
  62.  *****************************************************************************/
  63. char *cpystr(char *dest, char *src)
  64. {
  65.     char *r = dest;
  66.  
  67.     while (*src)
  68.     {
  69.         *dest = *src;
  70.         dest++;
  71.         src++;
  72.     }
  73.     *dest = '\0';
  74.     return(r);
  75. }
  76.  
  77. /*****************************************************************************
  78.  
  79.   Concatenates src onto dest.
  80.  
  81.  *****************************************************************************/
  82. char *catstr(char *dest, char *src)
  83. {
  84.     char *r = dest;
  85.  
  86.     while (*dest) dest++;
  87.  
  88.     while (*src)
  89.     {
  90.         *dest = *src;
  91.         dest++;
  92.         src++;
  93.     }
  94.     *dest = '\0';
  95.     return(r);
  96. }
  97.  
  98. /*****************************************************************************
  99.  
  100.   Copies src to dest, for no more than len characters.
  101.  
  102.  *****************************************************************************/
  103. char *cpystrn(char *dest, char *src, unsigned long len)
  104. {
  105.     unsigned long cur = 0;
  106.     char *r = dest;
  107.  
  108.     while ((cur < len) && (*src))
  109.     {
  110.         *dest = *src;
  111.         dest++;
  112.         src++;
  113.         cur++;
  114.     }
  115.     *dest = '\0';
  116.     return(r);
  117. }
  118.  
  119. /*****************************************************************************
  120.  
  121.   Concatenates src onto dest, dest will never be longer than len.
  122.  
  123.  *****************************************************************************/
  124. char *catstrn(char *dest, char *src, unsigned long len)
  125. {
  126.     unsigned long cur = 0;
  127.     char *r = dest;
  128.  
  129.     while (*dest)
  130.     {
  131.         cur++;
  132.         dest++;
  133.     }
  134.     if (cur < len)
  135.     {
  136.         while ((cur < len) && (*src))
  137.         {
  138.             *dest = *src;
  139.             dest++;
  140.             src++;
  141.             cur++;
  142.         }
  143.         *dest = '\0';
  144.     }
  145.     return(r);
  146. }
  147.  
  148. /*****************************************************************************
  149.  
  150.   Compares s1 to s2, case sensitive.
  151.  
  152.  *****************************************************************************/
  153. int cmpstr(char *s1, char *s2)
  154. {
  155.     while ((*s1) && (*s2))
  156.     {
  157.         if (*s1 < *s2)
  158.             return -1;
  159.         else if (*s1 > *s2)
  160.             return 1;
  161.  
  162.         s1++;
  163.         s2++;
  164.     }
  165.  
  166.     if ((!(*s1)) && (!(*s2)))
  167.         return 0;
  168.     else
  169.     {
  170.         if (!(*s1))
  171.             return -1;
  172.         else
  173.             return 1;
  174.     }
  175. }
  176.  
  177. /*****************************************************************************
  178.  
  179.   Compares s1 to s2, case insensitive.
  180.  
  181.  *****************************************************************************/
  182. int cmpstri(char *s1, char *s2)
  183. {
  184.     while ((*s1) && (*s2))
  185.     {
  186.         if (cupper(*s1) < cupper(*s2))
  187.             return -1;
  188.         else if (cupper(*s1) > cupper(*s2))
  189.             return 1;
  190.  
  191.         s1++;
  192.         s2++;
  193.     }
  194.  
  195.     if ((!(*s1)) && (!(*s2)))
  196.         return 0;
  197.     else
  198.     {
  199.         if (!(*s1))
  200.             return -1;
  201.         else
  202.             return 1;
  203.     }
  204. }
  205.  
  206. /*****************************************************************************
  207.  
  208.   Compares s1 to s2, no more than len characters are compared.
  209.  
  210.  *****************************************************************************/
  211. int cmpstrn(char *s1, char *s2, unsigned long len)
  212. {
  213.     unsigned long cur = 0;
  214.  
  215.     while ((*s1) && (*s2) && (cur<len))
  216.     {
  217.         if (*s1 < *s2)
  218.             return -1;
  219.         else if (*s1 > *s2)
  220.             return 1;
  221.  
  222.         s1++;
  223.         s2++;
  224.         cur++;
  225.     }
  226.  
  227.     if (((!(*s1)) && (!(*s2))) || (cur==len))
  228.         return 0;
  229.     else
  230.     {
  231.         if (!(*s1))
  232.             return -1;
  233.         else
  234.             return 1;
  235.     }
  236. }
  237.  
  238. /*****************************************************************************
  239.  
  240.   Compares s1 to s2, no more than len characters are compared,
  241.   case insensitive.
  242.  
  243.  *****************************************************************************/
  244. int cmpstrni(char *s1, char *s2, unsigned long len)
  245. {
  246.     unsigned long cur = 0;
  247.  
  248.     while ((*s1) && (*s2) && (cur<len))
  249.     {
  250.         if (cupper(*s1) < cupper(*s2))
  251.             return -1;
  252.         else if (cupper(*s1) > cupper(*s2))
  253.             return 1;
  254.  
  255.         s1++;
  256.         s2++;
  257.         cur++;
  258.     }
  259.  
  260.     if (((!(*s1)) && (!(*s2))) || (cur==len))
  261.         return 0;
  262.     else
  263.     {
  264.         if (!(*s1))
  265.             return -1;
  266.         else
  267.             return 1;
  268.     }
  269. }
  270.  
  271. /*****************************************************************************
  272.  
  273.   Determines the length of s.
  274.  
  275.  *****************************************************************************/
  276. unsigned long lenstr(char *s)
  277. {
  278.     unsigned long cur = 0;
  279.  
  280.     while (*s)
  281.     {
  282.         s++;
  283.         cur++;
  284.     }
  285.     return(cur);
  286. }
  287.  
  288. /*****************************************************************************
  289.  
  290.   Finds h in s, case sensitive.
  291.  
  292.  *****************************************************************************/
  293. char *strinstr(char *n, char *h)
  294. {
  295.     while (*n)
  296.     {
  297.         if (!cmpstrn(n, h, lenstr(h)))
  298.             return(n);
  299.         n++;
  300.     }
  301.  
  302.     return (char *)NULL;
  303. }
  304.  
  305. /*****************************************************************************
  306.  
  307.   Finds h in s, case insensitive.
  308.  
  309.  *****************************************************************************/
  310. char *strinstri(char *n, char *h)
  311. {
  312.     while (*n)
  313.     {
  314.         if (!cmpstrni(n, h, lenstr(h)))
  315.             return(n);
  316.         n++;
  317.     }
  318.  
  319.     return (char *)NULL;
  320. }
  321.  
  322. /*****************************************************************************
  323.  
  324.   Finds the first instance of c in s.
  325.  
  326.  *****************************************************************************/
  327. char *charinstr(char *s, char c)
  328. {
  329.     if (!c)
  330.     {
  331.         while (*s) s++;
  332.         return(s);
  333.     }
  334.     else
  335.     {
  336.         while (*s)
  337.         {
  338.             if (*s == c)
  339.                 return(s);
  340.             s++;
  341.         }
  342.         return (char *)NULL;
  343.     }
  344. }
  345.  
  346. /*****************************************************************************
  347.  
  348.   Finds the last instance of c in s.
  349.  
  350.  *****************************************************************************/
  351. char *rcharinstr(char *s, char c)
  352. {
  353.     unsigned long cur;
  354.  
  355.     cur = lenstr(s);
  356.  
  357.     if (cur)
  358.     {
  359.         while (*s) s++;
  360.         s--;
  361.         while (cur--)
  362.         {
  363.             if (*s == c)
  364.                 return(s);
  365.             s--;
  366.         }
  367.         return (char *)NULL;
  368.     }
  369.     else
  370.         return (char *)NULL;
  371. }
  372.  
  373. /*****************************************************************************
  374.  
  375.   Converts s to uppercase.
  376.  
  377.  *****************************************************************************/
  378. char *supper(char *s)
  379. {
  380.     char *p = s;
  381.  
  382.     while (*s)
  383.     {
  384.         *s = cupper(*s);
  385.         s++;
  386.     }
  387.     return(p);
  388. }
  389.  
  390. /*****************************************************************************
  391.  
  392.   Converts s to lowercase.
  393.  
  394.  *****************************************************************************/
  395. char *slower(char *s)
  396. {
  397.     char *p = s;
  398.  
  399.     while (*s)
  400.     {
  401.         *s = clower(*s);
  402.         s++;
  403.     }
  404.     return(p);
  405. }
  406.  
  407. /*****************************************************************************
  408.  
  409.   Moves s to d for l bytes, the regions may overlap.
  410.  
  411.  *****************************************************************************/
  412. void movemem(void *d, void *s, unsigned long l)
  413. {
  414.     char *pd = (char *)d,
  415.          *ps = (char *)s;
  416.     unsigned long i;
  417.  
  418.     if (pd<ps)
  419.     {
  420.         for (i=0; i<l; i++,pd++,ps++)
  421.             *pd = *ps;
  422.     }
  423.     else
  424.     {
  425.         pd += (l-1);
  426.         ps += (l-1);
  427.  
  428.         for (;l>0;l--,pd--,ps--)
  429.             *pd = *ps;
  430.     }
  431. }
  432.  
  433. /*****************************************************************************
  434.  
  435.   Sets the memory region d, with f for l bytes.
  436.  
  437.  *****************************************************************************/
  438. void setmem(void *d, char f, unsigned long l)
  439. {
  440.     char *pd = (char *)d;
  441.  
  442.     for (;l>0;l--,pd++)
  443.         *pd = f;
  444. }
  445.  
  446. /*****************************************************************************
  447.  
  448.   Converts an unsigned long into its string representation in buf.
  449.  
  450.  *****************************************************************************/
  451. char *ultoasc(unsigned long num, char *buf)
  452. {
  453.     char r[40];
  454.     char *p, *s;
  455.     long n;
  456.  
  457.     if (!num)
  458.         cpystr(buf, "0");
  459.     else
  460.     {
  461.         p = r;
  462.         *p = '\0';
  463.         while (num)
  464.         {
  465.             *p = '0' + (num % 10);
  466.             num /= 10;
  467.             p++;
  468.             *p = '\0';
  469.         }
  470.  
  471.         n = lenstr(r);
  472.         s = buf;
  473.         p = r;
  474.         p += (n-1);
  475.         while(n--)
  476.         {
  477.             *s = *p;
  478.             s++;
  479.             *s = '\0';
  480.             p--;
  481.         }
  482.     }
  483.     return(buf);
  484. }
  485.  
  486. /*****************************************************************************
  487.  
  488.   Converts a long into its string representation in buf.
  489.  
  490.  *****************************************************************************/
  491. char *ltoasc(long num, char *buf)
  492. {
  493.     char r[40];
  494.  
  495.     buf[0] = '\0';
  496.     if (num<0)
  497.     {
  498.         buf[0] = '-';
  499.         buf[1] = '\0';
  500.         num = -num;
  501.     }
  502.     catstrn(buf, ultoasc(num, r), 39);
  503.     return(buf);
  504. }
  505.  
  506. /*****************************************************************************
  507.  
  508.   Is character 'A...Z,a...z'?
  509.  
  510.  *****************************************************************************/
  511. int isalpha(char c)
  512. {
  513.     if (((c>='a') && (c<='z')) || ((c>='A') && (c<='Z')))
  514.         return 1;
  515.     else
  516.         return 0;
  517. }
  518.  
  519. /*****************************************************************************
  520.  
  521.   Is character '0...0'?
  522.  
  523.  *****************************************************************************/
  524. int isdig(char c)
  525. {
  526.     if (c>='0' && c<='9')
  527.         return 1;
  528.     else
  529.         return 0;
  530. }
  531.  
  532. /*****************************************************************************
  533.  
  534.   Is character ' \t\r\n'?
  535.  
  536.  *****************************************************************************/
  537. int iswspace(char c)
  538. {
  539.     int rc = 0;
  540.  
  541.     switch(c)
  542.     {
  543.         case '\t':
  544.         case '\r':
  545.         case '\n':
  546.         case ' ':
  547.             rc = 1;
  548.             break;
  549.     }
  550.     return(rc);
  551. }
  552.  
  553. /*****************************************************************************
  554.  
  555.   Converts the ASCII representation of a long value to a long.
  556.  
  557.  *****************************************************************************/
  558. long asctol(char *n)
  559. {
  560.     char *p;
  561.     int isneg = 0;
  562.     long num = 0;
  563.  
  564.     while ((*n) && (iswspace(*n)))
  565.         n++;
  566.  
  567.     if (*n)
  568.     {
  569.         if (*n=='-')
  570.         {
  571.             isneg = 1;
  572.             n++;
  573.         }
  574.  
  575.         while ((*n) && isdig(*n))
  576.         {
  577.             num = (num * 10) + ((long)(*n-'0'));
  578.             n++;
  579.         }
  580.  
  581.         if (isneg)
  582.             num = -num;
  583.     }
  584.     return(num);
  585. }
  586.  
  587. /*****************************************************************************
  588.  
  589.   Converts the ASCII representation of an unsigned long value to an unsigned
  590.   long.
  591.  
  592.  *****************************************************************************/
  593. unsigned long asctoul(char *n)
  594. {
  595.     char *p;
  596.     unsigned long num = 0;
  597.  
  598.     while ((*n) && (iswspace(*n)))
  599.         n++;
  600.  
  601.     if (*n)
  602.     {
  603.         while ((*n) && isdig(*n))
  604.         {
  605.             num = (num * 10) + ((long)(*n-'0'));
  606.             n++;
  607.         }
  608.     }
  609.     return(num);
  610. }
  611.  
  612. /*****************************************************************************
  613.  
  614.   Performs escape character translation on a subset of the C escape set.
  615.  
  616.  *****************************************************************************/
  617. unsigned char *translate(unsigned char *string)
  618. {
  619.     char *here=string;
  620.     size_t len=lenstr(string);
  621.     int num;
  622.     int numlen;
  623.  
  624.     while (NULL!=(here=charinstr(here,'\\')))
  625.     {
  626.         numlen=1;
  627.         switch (here[1])
  628.         {
  629.             case '\\':
  630.                 break;
  631.  
  632.             case 'r':
  633.                 *here = '\r';
  634.                 break;
  635.  
  636.             case 'n':
  637.                 *here = '\n';
  638.                 break;
  639.  
  640.             case 't':
  641.                 *here = '\t';
  642.                 break;
  643.  
  644.             case 'v':
  645.                 *here = '\v';
  646.                 break;
  647.  
  648.             case 'a':
  649.                 *here = '\a';
  650.                 break;
  651.         }
  652.         num = here - string + numlen;
  653.         here++;
  654.         movemem(here,here+numlen,len-num );
  655.     }
  656.     return string;
  657. }
  658.  
  659. /*****************************************************************************
  660.  
  661.   Scans the comma-delimited string i, returns one segment of it in o.
  662.   Commas inside double quoted (") string segments are ignored. If you need
  663.   double quotes in the string double them up (""). Double quotes must be
  664.   paired up.. I.E; ""22, 22"".
  665.  
  666.   If the input string is:
  667.  
  668.     "22, 34", 25
  669.  
  670.   On return o would contain `22, 34' and i would be pointing just past the
  671.   second "," in the input string.
  672.  
  673.  *****************************************************************************/
  674. char *GetNextString(char *i, char *o)
  675. {
  676.     int inQuotes = 0;
  677.  
  678.     while ((iswspace(*i)) && (*i)) i++;
  679.  
  680.     while (*i)
  681.     {
  682.         if (*i=='"')
  683.         {
  684.             i++;
  685.             inQuotes = ~inQuotes;
  686.         }
  687.  
  688.         if ((!inQuotes) && (*i == ','))
  689.             break;
  690.  
  691.         *o = *i;
  692.         i++;
  693.         o++;
  694.     }
  695.  
  696.     *o = '\0';
  697.  
  698.     return(((*i != 0) ? i+1 : i));
  699. }
  700.  
  701. /*****************************************************************************
  702.  
  703.   Performs a subset of the tranlsations and substitutions that the printf()
  704.   family of run-time library functions do.
  705.  
  706.   Format specifiers are simple, the recognized specifiers are:
  707.  
  708.     %%  %
  709.     %s  String
  710.     %u  Unsigned Long
  711.     %d  Long
  712.  
  713.   Escape characters recognized are:
  714.  
  715.     \\  \
  716.     \"  "
  717.     \r  carriage return
  718.     \n  linefeed
  719.     \t  tab
  720.     \v  vertical tab
  721.     \a  bell
  722.  
  723.   items[] is an array of unsigned longs. It is your responsibility to make
  724.   sure that there are as many elements in items[] as there are format
  725.   specifiers in fmt.
  726.  
  727.   It is also your responsibility to make sure that buf is large enough to
  728.   contain all the translations in fmt.
  729.  
  730.   The return value is the number of format specifiers converted.
  731.  
  732.  *****************************************************************************/
  733. int formatStr(char *buf, char *fmt, unsigned long *items)
  734. {
  735.     char n[32];
  736.     char *s;
  737.     unsigned long ul;
  738.     long l;
  739.     int i = 0;
  740.  
  741.     while(*fmt)
  742.     {
  743.         if (*fmt=='%')
  744.         {
  745.             fmt++;
  746.             switch(*fmt)
  747.             {
  748.                 case 's':
  749.                     s = (char *)items[i];
  750.                     cpystr(buf, s);
  751.                     i++;
  752.                     buf += lenstr(buf);
  753.                     break;
  754.  
  755.                 case 'u':
  756.                     ul = (unsigned long)items[i];
  757.                     cpystr(buf, ultoasc(ul, n));
  758.                     i++;
  759.                     buf += lenstr(buf);
  760.                     break;
  761.  
  762.                 case 'l':
  763.                     l = (long)items[i];
  764.                     cpystr(buf, ltoasc(l, n));
  765.                     i++;
  766.                     buf += lenstr(buf);
  767.                     break;
  768.  
  769.                 default:
  770.                     *buf = *fmt;
  771.                     buf++;
  772.                     *buf = 0;
  773.                     break;
  774.             }
  775.         }
  776.         else
  777.         {
  778.             if (*fmt=='\\')
  779.             {
  780.                 fmt++;
  781.                 switch(*fmt)
  782.                 {
  783.                     case '\\':
  784.                         *buf = '\\';
  785.                         break;
  786.  
  787.                     case '"':
  788.                         *buf = '"';
  789.                         break;
  790.  
  791.                     case 'r':
  792.                         *buf = '\r';
  793.                         break;
  794.  
  795.                     case 'n':
  796.                         *buf = '\n';
  797.                         break;
  798.  
  799.                     case 't':
  800.                         *buf = '\t';
  801.                         break;
  802.  
  803.                     case 'v':
  804.                         *buf = '\v';
  805.                         break;
  806.  
  807.                     case 'a':
  808.                         *buf = '\a';
  809.                         break;
  810.  
  811.                     default:
  812.                         *buf = *fmt;
  813.                         break;
  814.                 }
  815.                 buf++;
  816.                 *buf = 0;
  817.             }
  818.             else
  819.             {
  820.                 *buf = *fmt;
  821.                 buf++;
  822.                 *buf = 0;
  823.             }
  824.         }
  825.         fmt++;
  826.     }
  827.  
  828.     return(i);
  829. }
  830.