home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / quot210s.zip / xtype / src / xstr.c < prev    next >
C/C++ Source or Header  |  1998-12-15  |  8KB  |  364 lines

  1. /*
  2.  * xstr.c
  3.  *
  4.  * Extensible string routines.
  5.  *
  6.  *      Created: 21st January 1998
  7.  * Version 1.00: 10th December 1998
  8.  *
  9.  * (C) 1998 Nicholas Paul Sheppard. See the file licence.txt for details.
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "xtype.h"
  16.  
  17.  
  18. /* internal function prototypes */
  19. int    _cgetc(FILE *);            /* hack for getc() */
  20.  
  21.  
  22. XSTR *fgetxstr(XSTR *xstr, FILE *f)
  23. /*
  24.  * Read a line from a file, as fgets().
  25.  *
  26.  * XSTR *xstr    - the extensible string to read the line into
  27.  * FILE *f    - the file to read from
  28.  *
  29.  * Returns    - xstr, if the line was read successfully
  30.  *          NULL, if there was an error (feof() or ferror(), otherwise memory allocation)
  31.  */
  32. {
  33.     int    ch;    /* read buffer */
  34.  
  35.     /* start with an empty string */
  36.     xstr->pszString[0] = '\0';
  37.  
  38.     if ((ch = _cgetc(f)) == EOF)
  39.         return (NULL);
  40.     if (xstrcatc(xstr, (char)ch) == NULL)
  41.         return (NULL);
  42.     while ((ch != '\n') && (ch != EOF)) {
  43.         if ((ch = _cgetc(f)) != EOF) {
  44.             if (xstrcatc(xstr, (char)ch) == NULL)
  45.                 return (NULL);
  46.         }
  47.     }
  48.  
  49.     if ((ch == EOF) && !feof(f))
  50.         return (NULL);
  51.  
  52.     return (xstr);
  53. }
  54.  
  55.  
  56. XSTR *xstrcat(XSTR *xstr, char *psz)
  57. /*
  58.  * Concatenate a string to the end of an extensible string.
  59.  *
  60.  * XSTR *xstr    - the extensible string to be concatenated to
  61.  * char *psz    - the string to concatenate to xstr
  62.  *
  63.  * Returns    - NULL if there is a memory allocation failure
  64.  *          xstr, otherwise
  65.  */
  66. {
  67.     int    iReq;        /* space required for new string */
  68.     int    iNewSize;    /* new size of xstr */
  69.     char *    pch;        /* temporary pointer */
  70.  
  71.     /* ensure that xstr is long enough to hold the concatenation */
  72.     iReq = xstrlen(xstr) + strlen(psz) + 1;
  73.     if (xstr->iSize <= iReq) {
  74.         iNewSize = xstr->iSize;
  75.         while (iNewSize <= iReq)
  76.             iNewSize += xstr->iBlock;
  77.         if ((pch = (char *)realloc(xstr->pszString, iNewSize)) == NULL)
  78.             return (NULL);
  79.         else {
  80.             xstr->pszString = pch;
  81.             xstr->iSize = iNewSize;
  82.         }
  83.     }
  84.  
  85.     /* concatenate */
  86.     strcat(xstrcast(xstr), psz);
  87.  
  88.     return (xstr);
  89. }
  90.  
  91.  
  92. XSTR *xstrcatc(XSTR *xstr, char ch)
  93. /*
  94.  * Concatenate a character to the end of an extensible string.
  95.  *
  96.  * XSTR *xstr    - the extensible string to be concatenated to
  97.  * char ch    - the character to concatenate to xstr
  98.  *
  99.  * Returns    - NULL if there is a memory allocation failure
  100.  *          xstr, otherwise
  101.  */
  102. {
  103.     char *    pch;        /* temporary pointer */
  104.  
  105.     /* ensure that xstr is long enough to hold the concatenation */
  106.     if (xstr->iSize <= (xstrlen(xstr) + 1)) {
  107.         if ((pch = (char *)realloc(xstr->pszString, xstr->iSize + xstr->iBlock)) == NULL)
  108.             return (NULL);
  109.         else {
  110.             xstr->pszString = pch;
  111.             xstr->iSize += xstr->iBlock;
  112.         }
  113.     }
  114.  
  115.     /* concatenate */
  116.     pch = strchr(xstr->pszString, '\0');
  117.     *pch = ch;
  118.     *(pch + 1) = '\0';
  119.  
  120.     return (xstr);
  121. }
  122.  
  123.  
  124. XSTR *xstrcpy(XSTR *xstr, char *psz)
  125. /*
  126.  * Copy a string into an extensible string.
  127.  *
  128.  * XSTR *xstr    - destination
  129.  * char *psz    - source
  130.  *
  131.  * Returns    - NULL if there is a memory allocation failure
  132.  *          xstr, otherwise
  133.  */
  134. {
  135.     int    iReq;        /* space required for new string */
  136.     int    iNewSize;    /* new size of xstr */
  137.     char *    pch;        /* temporary pointer */
  138.  
  139.     /* ensure that xstr is long enough to hold psz */
  140.     iReq = strlen(psz) + 1;
  141.     if (xstr->iSize <= iReq) {
  142.         iNewSize = xstr->iSize;
  143.         while (iNewSize <= iReq)
  144.             iNewSize += xstr->iBlock;
  145.         if ((pch = (char *)realloc(xstr->pszString, iNewSize)) == NULL)
  146.             return (NULL);
  147.         else {
  148.             xstr->pszString = pch;
  149.             xstr->iSize = iNewSize;
  150.         }
  151.     }
  152.  
  153.     /* copy */
  154.     strcpy(xstrcast(xstr), psz);
  155.  
  156.     return (xstr);
  157. }
  158.  
  159.  
  160. char *xstrcvt(XSTR *xstr)
  161. /*
  162.  * Convert an extensible string into a normal string (i.e. get rid of all the
  163.  * extraneous stuff extenesible strings use). Do not use xstr after calling
  164.  * this function.
  165.  *
  166.  * XSTR *xstr    - the extensible string to be converted.
  167.  *
  168.  * Returns    - (a pointer to) the null-terminated string represented by xstr
  169.  */
  170. {
  171.     char *    pszString;    /* return value */
  172.  
  173.     if (xstr != NULL) {
  174.         pszString = xstr->pszString;
  175.         free(xstr);
  176.     } else {
  177.         pszString = NULL;
  178.     }
  179.  
  180.     return (pszString);
  181. }
  182.  
  183.  
  184. XSTR *xstrdel(XSTR *xstr, int iStart, int iEnd)
  185. /*
  186.  * Delete a portion of an extensible string.
  187.  *
  188.  * XSTR *xstr    - the extensible string
  189.  * int iStart    - the index of the first character to be removed
  190.  * int iEnd    - the index of the last character to be removed
  191.  *
  192.  * Returns    - xstr
  193.  */
  194. {
  195.     memmove(xstr->pszString + iStart, xstr->pszString + iEnd + 1, xstrlen(xstr) - iEnd);
  196.  
  197.     return (xstr);
  198. }
  199.  
  200.  
  201. void xstrfree(XSTR *xstr)
  202. /*
  203.  * Free the memory used by an extensible string.
  204.  *
  205.  * XSTR *xstr    - pointer to the memory to be freed.
  206.  */
  207. {
  208.     if (xstr != NULL) {
  209.         free(xstr->pszString);
  210.         free(xstr);
  211.     }
  212. }
  213.  
  214.  
  215. XSTR *xstrncat(XSTR *xstr, char *psz, int n)
  216. /*
  217.  * Concatenate a string to the end of an extensible string up to a given
  218.  * length.
  219.  *
  220.  * XSTR *xstr    - the extensible string to be concatenated to
  221.  * char *psz    - the string to concatenate to xstr
  222.  * int n    - the maximum number of characters to concatenate
  223.  *
  224.  * Returns    - NULL if there is a memory allocation failure
  225.  *          xstr, otherwise
  226.  */
  227. {
  228.     int    iReq;        /* space required for new string */
  229.     int    iNewSize;    /* new size of xstr */
  230.     char *    pch;        /* temporary pointer */
  231.  
  232.     /* ensure that xstr is long enough to hold the concatenation */
  233.     if ((iReq = strlen(psz)) > n)
  234.         iReq = n;
  235.     iReq += xstrlen(xstr);
  236.     if (xstr->iSize <= iReq) {
  237.         iNewSize = xstr->iSize;
  238.         while (iNewSize <= iReq)
  239.             iNewSize += xstr->iBlock;
  240.         if ((pch = (char *)realloc(xstr->pszString, iNewSize)) == NULL)
  241.             return (NULL);
  242.         else {
  243.             xstr->pszString = pch;
  244.             xstr->iSize = iNewSize;
  245.         }
  246.     }
  247.  
  248.     /* concatenate */
  249.     strncat(xstrcast(xstr), psz, n);
  250.  
  251.     return (xstr);
  252. }
  253.  
  254.  
  255. XSTR *xstrncpy(XSTR *xstr, char *psz, int n)
  256. /*
  257.  * Copy a string into an extensible string up a given length.
  258.  *
  259.  * XSTR *xstr    - destination
  260.  * char *psz    - source
  261.  * int n    - the maximum number of characters to copy
  262.  *
  263.  * Returns    - NULL if there is a memory allocation failure
  264.  *          xstr, otherwise
  265.  */
  266. {
  267.     int    iReq;        /* space required for new string */
  268.     int    iNewSize;    /* new size of xstr */
  269.     char *    pch;        /* temporary pointer */
  270.  
  271.     /* ensure that xstr is long enough to hold psz */
  272.     if ((iReq = strlen(psz)) > (n + 1))
  273.         iReq = n + 1;
  274.     if (xstr->iSize <= iReq) {
  275.         iNewSize = xstr->iSize;
  276.         while (iNewSize <= iReq)
  277.             iNewSize += xstr->iBlock;
  278.         if ((pch = (char *)realloc(xstr->pszString, iNewSize)) == NULL)
  279.             return (NULL);
  280.         else {
  281.             xstr->pszString = pch;
  282.             xstr->iSize = iNewSize;
  283.         }
  284.     }
  285.  
  286.     /* copy */
  287.     strncpy(xstrcast(xstr), psz, n);
  288.     xstr->pszString[n] = '\0';
  289.  
  290.     return (xstr);
  291. }
  292.  
  293.  
  294. XSTR *xstrnew(int iSize, int iBlock)
  295. /*
  296.  * Create a new extensible string.
  297.  *
  298.  * int iSize    - the initial size of the string
  299.  * int iBlock    - the size the string should grow by
  300.  *
  301.  * Returns    - NULL if there is a memory allocation failure
  302.  *          a pointer to a new extensible string, otherwise
  303.  */
  304. {
  305.     XSTR *    xstr;    /* return value */
  306.  
  307.     if ((xstr = (XSTR *)malloc(sizeof(XSTR))) != NULL) {
  308.         xstr->iSize = iSize;
  309.         xstr->iBlock = iBlock;
  310.         if ((xstr->pszString = (char *)malloc(iSize)) == NULL) {
  311.             free(xstr);
  312.             xstr = NULL;
  313.         } else {
  314.             xstr->pszString[0] = '\0';
  315.         }
  316.     }
  317.  
  318.     return (xstr);
  319. }
  320.  
  321.  
  322. XSTR *xstrtrunc(XSTR *xstr, int n)
  323. /*
  324.  * Truncate an extensible string.
  325.  *
  326.  * XSTR *xstr    - the string to be truncated
  327.  * int n    - the number of characters to truncate to
  328.  *
  329.  * Returns    - xstr
  330.  */
  331. {
  332.     if (n < xstr->iSize)
  333.         xstr->pszString[n] = '\0';
  334.  
  335.     return (xstr);
  336. }
  337.  
  338.  
  339. int _cgetc(FILE *f)
  340. /*
  341.  * Hack to make getc() return '\n' for all end-of-line regimes (that this
  342.  * author has heard of).
  343.  *
  344.  * FILE *f    - stream to read from
  345.  *
  346.  * Returns    - EOF on error
  347.  *          the character read, otherwise
  348.  */
  349. {
  350.     static int    bCR = 0;    /* was the last character read '\r'? */
  351.     int        ch;        /* return value */
  352.  
  353.     if ((ch = getc(f)) == '\r') {
  354.         bCR = 1;
  355.         ch = '\n';
  356.     } else if (bCR) {
  357.         bCR = 0;
  358.         if (ch == '\n')
  359.             ch = _cgetc(f);
  360.     }
  361.  
  362.     return (ch);
  363. }
  364.