midrange.com code scratchpad
Name:
buffread0
Scriptlanguage:
Plain Text
Tabwidth:
4
Date:
02/05/2009 10:52:53 pm
IP:
Logged
Description:
Reading an IFS stream file looking for arbitrary-length record delimiters (Unix API version).
QCOPYSRC,UTTIFS is Scott Klements IFSIO_H by a different name.
Code:
  1.      D getRecord       PR            10I 0
  2.      D  file                         10I 0 VALUE
  3.      D  record                    65535A   VARYING
  4.      D                                     OPTIONS(*VARSIZE)
  5.      D  maxSize                      10I 0 VALUE
  6.      D  recordStart...
  7.      D                               10A   VARYING
  8.      D                                     CONST
  9.      D  recordEnd...
  10.      D                               10A   VARYING
  11.      D                                     CONST
  12.  
  13.       /copy QCOPYSRC,UTTIFS
  14.  
  15.      D fd...
  16.      D                 S                   like(open)
  17.      D reclen...
  18.      D                 S                   like(getRecord)
  19.      D record...
  20.      D                 S            500A   varying
  21.      D start...
  22.      D                 S               z
  23.      D end...
  24.      D                 S               z
  25.      D runtime...
  26.      D                 S             11A   dtaara('RUNTIME')
  27.       /free
  28.        start = %timestamp();
  29.  
  30.        fd = open('/home/adamg/readtest/onebig' : O_RDONLY + O_TEXTDATA);
  31.  
  32.        recLen = getRecord(fd : record : %size(record) -2 : '<B>' : '<E>');
  33.        dow (reclen > 0);
  34.          recLen = getRecord(fd : record : %size(record) -2 : '<B>' : '<E>');
  35.        enddo;
  36.  
  37.        callp close(fd);
  38.  
  39.        end = %timestamp();
  40.  
  41.        in *lock runTime;
  42.        runTime = %char(%diff(end : start : *ms));
  43.        out runTime;
  44.  
  45.        *inlr = *on;
  46.        return;
  47.       /end-free
  48.  
  49.      P*--------------------------------------------------
  50.      P* Procedure name: getRecord
  51.      P* Purpose:        Retrieve one event or alarm record from the file
  52.      P* Returns:        The number of bytes in the record, -1 if an error o...
  53.      P*                          ccurred
  54.      P* Parameter:      file => The file from which to read
  55.      P* Parameter:      record => The variable which will receive the record
  56.      P* Parameter:      maxSize => The maximum number of bytes that the rec...
  57.      P*                          ord variable can hold
  58.      P*--------------------------------------------------
  59.      P getRecord       B
  60.      D getRecord       PI            10I 0
  61.      D  file                         10I 0 VALUE
  62.      D  record                    65535A   VARYING
  63.      D                                     OPTIONS(*VARSIZE)
  64.      D  maxSize                      10I 0 VALUE
  65.      D  recordStart...
  66.      D                               10A   VARYING
  67.      D                                     CONST
  68.      D  recordEnd...
  69.      D                               10A   VARYING
  70.      D                                     CONST
  71.  
  72.  
  73.      D* Local fields
  74.      D buffer...
  75.      D                 S           1024A   static
  76.      D bufferPosition...
  77.      D                 S              5I 0 static
  78.      D bytesInBuffer...
  79.      D                 S              5I 0 static
  80.      D readTo...
  81.      D                 S               *
  82.      D recordStarted...
  83.      D                 S               N
  84.      D reloadRequested...
  85.      D                 S               N
  86.      D bytesInRecord   S             10I 0
  87.      D readFromFile...
  88.      D                 S                   like(bytesInBuffer)
  89.      D unreadCount...
  90.      D                 S                   like(bytesInBuffer)
  91.  
  92.       /free
  93.        // "clear out" the variable that will receive the record
  94.        %len(record) = 0;
  95.  
  96.        dow (1 = 1);
  97.          // reload the buffer when necessary
  98.          if (bufferPosition >= bytesInBuffer OR reloadRequested);
  99.            reloadRequested = *OFF;
  100.            unreadCount = bytesInBuffer-bufferPosition;
  101.            if (unreadCount < 0);
  102.              unreadCount = 0;
  103.            endif;
  104.  
  105.            if (unreadCount > 0);
  106.              // if there are still some characters which haven't been
  107.              //  read due to a forced reload of the buffer, they need to be
  108.              //  put to the beginning of the buffer
  109.              // At this point, bufferPosition points the the last character
  110.              //  that was processed, so we want bufferPosition+1 to the end
  111.              buffer = %subst(buffer : bufferPosition + 1);
  112.            endif;
  113.  
  114.            // fill the buffer starting after any characters that are left
  115.            //  over from the last read
  116.            bufferPosition = 0;
  117.            readTo = %addr(buffer) + unreadCount;
  118.            readFromFile = read(file : readTo : %size(buffer) - unreadCount);
  119.            if (readFromFile < 1);
  120.              // error reading file or end of file, return error code
  121.              buffer = *blanks;
  122.              bytesInBuffer = 0;
  123.              bufferPosition = 0;
  124.              return -1;
  125.            endif;
  126.  
  127.            bytesInBuffer = unreadCount + readFromFile;
  128.  
  129.          endif;
  130.  
  131.          // read the next section of the buffer
  132.          if (NOT recordStarted);
  133.            if ((bytesInBuffer-bufferPosition) < %len(recordStart));
  134.              // not enough bytes left in buffer for start of record sequence,
  135.              //   so reload the buffer with unread part still included
  136.              reloadRequested = *on;
  137.              iter;
  138.            endif;
  139.  
  140.            bufferPosition += 1;
  141.            if (recordStart =
  142.                    %subst(buffer : bufferPosition : %len(recordStart))
  143.                   );
  144.              recordStarted = *ON;
  145.  
  146.              // start of record sequence should not be included in the
  147.              //   returned record
  148.              bufferPosition += %len(recordStart) - 1;
  149.  
  150.            endif;
  151.            iter;
  152.  
  153.          endif;
  154.  
  155.          // check for end of record
  156.          if ((bytesInBuffer-bufferPosition) < %len(recordEnd));
  157.            // not enough bytes left in buffer for end of record sequence,
  158.            //   so reload the buffer with unread part still included
  159.            reloadRequested = *on;
  160.            iter;
  161.          endif;
  162.  
  163.          bufferPosition += 1;
  164.          if (recordEnd =
  165.                  %subst(buffer : bufferPosition : %len(recordEnd))
  166.                 );
  167.            // found end of record, so exit the read loop
  168.            bufferPosition += %len(recordEnd) - 1;
  169.            leave;
  170.          endif;
  171.  
  172.          // this character belongs in the record, so add it
  173.          bytesInRecord  += 1;
  174.          if (%len(record) < maxSize);
  175.            record += %subst(buffer : bufferPosition : 1);
  176.          endif;
  177.        enddo;
  178.  
  179.        return bytesInRecord;
  180.  
  181.       /end-free
  182.      P getRecord       E 
© 2004-2019 by midrange.com generated in 0.007s valid xhtml & css