Buffer Mainpulation

Technical Notes

Overview
Copying from One Buffer to Another
Comparing Buffers
Sample Program

Overview

This unit consists of functions which compare and move bytes between buffers of arbitrary size. These functions manage both buffers by indicating when the end of either buffer is encountered and maintaining buffer pointers and counts so the operation may be continued after the empty (or full) buffer has been refilled (or emptied). These functions are useful for characters or objects which are read from a source buffer and then modified and written to an output buffer.

Copying from One Buffer to Another

_buf_cpy
Copies the contents of one buffer to another.
_buf_ccpy
Copies the contents of one buffer, up to a given character, to another.
_fbuf_cpy
Far pointer version of _buf_cpy for small data models.
_fbuf_ccpy
Far pointer version of _buf_ccpy for small data models.
These functions copy data from one buffer to another. Copying terminates when the end of one of the buffers is reached. Upon completion of the operation, the returned pointers and counts reflect the position where copying stopped. _buf_cpy copies an entire buffer. _buf_ccpy copies until it encounters a specified character.

Comparing Buffers

_buf_cmp
Compares the contents of one buffer with another and returns pointers to mismatching bytes or the bytes following the last bytes compared.
_buf_cmpi
Compares the contents of one buffer with the contents of another (ignoring case) and returns pointers to mismatching bytes or the bytes following the last bytes compared.
_fbuf_cmp
Far pointer version of _buf_cmp for small data models.
_fbuf_cmpi
Far pointer version of _buf_cmpi for small data models.
These functions compare data in two different buffers. The comparison terminates when the end of one of the buffers is reached. Upon completion of the operation, the returned pointers and counts reflect the position in each buffer where the comparison stopped. If the buffers are identical up to the end of the smaller one, the size of the exhausted buffer will be returned as zero. The exhausted buffer may be filled with additional data, the pointer set back to the beginning of the buffer, and the size set to the new size of the buffer. The function may then be called again and the comparison will continue where it left off in the larger buffer. _buf_cmp uses a case-sensitive comparison to compare buffers. _buf_cmpi ignores the case of ASCII characters during comparison.

Sample Program

The LF2CRLF program shown below demonstrates how some of the buffer manipulation functions are used. The program is listed in its entirety.

#include 
#include 
#include 
#include 
#include 
#define LF 10
#define CR 13

char       buf1[80];                                    /* source buffer */
char    buf2[320];                                      /* destination buffer */
char       crlf[] = "\r\n";                             /* insert string */
char    sfname[80], ch, dfname[80], ftemp[13];
int        inhandle, outhandle;                 		/* file handles */
int        bufstat;                                     /* status of buffer copies */
int        nbytes;
unsigned int srcsize, destsize = sizeof(buf2)-1, insize = sizeof(crlf)-1;
void *srcbuf = buf1, *destbuf = buf2;
void *inbuf = crlf;

char   msg[] = "LF2CRLF   Converts single linefeeds into carriage return/linefeed pairs.\r\n\
          SYNTAX:   LF2CRLF [path]filename.ext\r\n\
          NOTES:    This utility converts linefeeds(LF) in the source\r\n\
          file to carriage return/linefeeds (CR/LF) in the\r\n\
          destination file. CR/LF pairs from the source file\r\n\
          are not modified. The destination filename will be\r\n\
          filename.NEW\r\n";
int main()
{
   if (!_arg_count())
   {
      _put_str(msg);
      return;
   }
   inhandle = _openex_h(_arg_next(sfname, &ch),O_RDONLY);
   if (inhandle == -1)
   {
      _put_str("Unable to open file ");
      _put_str(sfname);
      return;
   }
   _split_path(dfname, sfname);
   _split_fname(ftemp, sfname);
   _str_cat(dfname, ftemp);                     /* copy path and filename */
   _str_cat(dfname, ".new");                    /* append extension */
   outhandle = _open_h(dfname, O_RDWR+O_CREAT+O_TRUNC);
   if (outhandle == -1)
      _put_str("Unable to open output file");
   nbytes = _read_h(inhandle, buf1, sizeof(buf1)-1);
   srcsize = nbytes;
   while (nbytes != 0)
   {
      bufstat = _buf_ccpy(&srcbuf, &srcsize, &destbuf, &destsize, LF);
      if (bufstat == 1)                                 /* is source buffer empty? */
      {                                                 /*   y: feed it */
         nbytes = _read_h(inhandle, buf1, sizeof(buf1)-1);
         srcbuf = buf1;
         srcsize = nbytes;
      }
      if (bufstat == -1)                                /* is destination buffer full? */
      {                                                 /*   y: flush it */
         _write_h(outhandle, buf2, sizeof(buf2)-1);
         destbuf = buf2;
         destsize = sizeof(buf2)-1;
      }
      if (bufstat == 0)                                 /* has a linefeed been found? */
      {                                                 /*   y: CR\LF already exist? */
         if (*(char*)((char *)destbuf-2) != CR) /*  n: don't copy CR */
         {                                              /*  y: insert CR in destination buffer */
            ((char*)destbuf)--;
            destsize--;
            bufstat = _buf_cpy(&inbuf, &insize, &destbuf, &destsize);
            inbuf = crlf;
            insize = sizeof(crlf)-1;
            if (bufstat == 0)                   		/* did CR\LF fill destination buffer? */
            {                                           /*   y: flush it */
               _write_h(outhandle, buf2, sizeof(buf2)-1);
               destbuf = buf2;
               destsize = sizeof(buf2)-1;
               _buf_cpy(&inbuf, &insize, &destbuf, &destsize);
            }
         }
      }
   }
   destsize = sizeof(buf2)-1 - destsize;
   _write_h(outhandle, buf2, destsize); 				/* flush destination buffer */
   return;
}
A sample program similar to the above is provided on the distribution diskettes as REPLACE.C and may be compiled and linked using the following Microsoft C and Borland C command lines:

Microsoft C:


cl /c /I\msc\include /I\sa\include replace.c
link replace,replace,,\sa\lib\_sas \msc\lib\slibce
Borland C:

bcc /c /ms /I\bc\include /I\sa\include replace.c
tlink \bc\lib\c0s replace,replace,,\sa\lib\_sas \bc\lib\cs