home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / RECIO110.ZIP / DESIGN.TXT < prev    next >
Text File  |  1994-03-28  |  8KB  |  186 lines

  1.     Title: RECIO DESIGN AND DEVELOPMENT NOTES
  2. Copyright: (C) 1994 William Pierpoint
  3.   Version: 1.10
  4.      Date: March 28, 1994
  5.  
  6.  
  7.  
  8. 1.0 DATA STRUCTURES
  9.  
  10. 1.1 REC structure for each record stream
  11.  
  12.     * defined in recio.h.
  13.     * one static REC for recin (included in ROPEN_MAX count).
  14.     * allocate dynamic array of RECs dimensioned to ROPEN_MAX-1 in ropen().
  15.     * Each REC has two associated buffers:
  16.       1) record string buffer containing current record; 
  17.          allocate when first record read; 
  18.          reallocate if record becomes larger.
  19.       2) field string buffer containing current field;
  20.          allocate when first field read; 
  21.          reallocate if field becomes larger.
  22.     * deallocate dynamic RECs and associated buffers in rclose() and 
  23.       rcloseall() if all record streams closed; deallocate associated 
  24.       buffers for recin with an exit function registered with atexit().
  25.  
  26. 1.2 Accessing REC Members and Associated Buffers
  27.  
  28.     How do I
  29.     * access the name of the record stream?           rnames()
  30.     * access the current context number?              rcxtno()
  31.     * access the current record number?               rrecno()
  32.     * access the current field number?                rfldno()
  33.     * access the current column number?               rcolno()
  34.     * access the record string buffer?                rrecs()
  35.     * access the field string buffer?                 rflds()
  36.     * determine if column numbers start at 0 or 1     rbegcolno()
  37.     * determine if there are more records left?       reof()
  38.     * determine if there is an error on the stream?   rerror()
  39.     * force an error on a record stream?              rseterr()
  40.     * clear an error on a record stream?              rclearerr()
  41.     * increase the size of the record string buffer?  rsetrecsiz()
  42.     * increase the size of the field string buffer?   rsetfldsiz()
  43.     * replace the data in the field string buffer?    rsetfldstr()
  44.     * set the field delimiter character?              rsetfldch()
  45.     * set the text delimiter character?               rsettxtch()
  46.     * set the context number?                         rsetcxtno()
  47.     * set column numbering to start at 0 or 1         rsetbegcolno()
  48.  
  49.  
  50.  
  51. 2.0 CODE STRUCTURES
  52.  
  53. 2.1 Callback Error Function Skeleton
  54.  
  55.     if valid record pointer [isvalid(rp)]
  56.         if past end of file [reof(rp)]
  57.         else [error number set]
  58.             switch error number [rerror(rp)]
  59.             case data errors [R_ERANGE || R_EINVDAT || R_EMISDAT]
  60.                 switch context number [rcxtno(rp)]
  61.                 case RECIN
  62.                     switch field number [rfldno(rp)]
  63.                     case 1
  64.                     ...
  65.                     endcase
  66.                 ...
  67.                 default [missing or unknown context number]
  68.                 endcase
  69.             case out of memory [R_ENOMEM]
  70.             case non-fatal errors [R_ENOREG]
  71.             case fatal errors [R_EINVAL]
  72.             default [possibly set by application with rseterr()]
  73.             endcase
  74.         endif
  75.     else [invalid record pointer]
  76.         switch error number [errno]
  77.         case out of memory [ENOMEM]
  78.         case out of record or file pointers [EMFILE]
  79.         case permission denied [EACCES]
  80.         case fatal errors [EINVAL]
  81.         default [possibly set by application with rseterr()]
  82.         endcase
  83.     endif
  84.  
  85. 2.2 Classes of Field Functions
  86.  
  87.     There are four classes of functions that return field values:
  88.     
  89.     rget   - character delimited field, base 10 if numeric field
  90.     rbget  - numeric character delimited field, base 0 & 2-36
  91.     rcget  - column delimited field, base 10 if numeric field
  92.     rcbget - numeric column delimited field, base 0 & 2-36
  93.  
  94. 2.3 How to Define and Declare New Field Functions
  95.  
  96.     You can define a new function to get data using one of these macros:
  97.     
  98.     macro:         macro defined in:    define new function in:
  99.     -----------    -----------------    -----------------------
  100.     rget_fn()      _rget.h              rget.c
  101.     rbget_fn()     _rbget.h             rbget.c
  102.     rcget_fn()     _rcget.h             rcget.c
  103.     rcbget_fn()    _rcbget.h            rcbget.c
  104.  
  105.     macro:         declare new function in recio.h as:
  106.     -----------    ---------------------------------------------------------
  107.     rget_fn()      rget?(REC *rp);
  108.     rbget_fn()     rbget?(REC *rp, int base);
  109.     rcget_fn()     rcget?(REC *rp, size_t begcol, size_t endcol);
  110.     rcbget_fn()    rcbget?(REC *rp, size_t begcol, size_t endcol, int base);
  111.                    where ? is one or more new unique letters
  112.                    
  113.     All four macros have the same seven arguments:
  114.     --------------------------------------------------
  115.     fn_type        defined function return type
  116.     fn_name        defined function name
  117.     fn_err         defined function error return value
  118.     cv_type        conversion function return type
  119.     cv_name        conversion function name
  120.     fn_min         inclusive valid minimum value
  121.     fn_max         inclusive valid maximum value
  122.  
  123.     The commonly used conversion functions are:
  124.     
  125.     name:          return type:
  126.     -------        -------------
  127.     strtol         long
  128.     strtoul        unsigned long
  129.     strtod         double
  130.     strtoc         character (portability note: strtoc violates 
  131.                               ansi-c reserved namespace)
  132.  
  133.     Example: suppose you want to define a function rgetb() that gets a 
  134.              boolean value (unsigned char) and generates an ERANGE error 
  135.              if the value is not 0 or 1:
  136.  
  137.      /* definition to add to rget.c */
  138.      rget_fn(unsigned char, rgetb, 0, long, strtol, 0,  1)
  139.  
  140.      /* declaration to add to recio.h */
  141.      rgetb(REC *rp);
  142.  
  143.      --OR to generate an EINVDAT error if the value is not 0 or 1--
  144.      
  145.      /* definition to add to rbget.c */
  146.      rbget_fn(unsigned char, rbgetb, 0, long, strtol, 0,  1)
  147.      
  148.      /* declaration to add to recio.h */
  149.      rbgetb(REC *rp, int base);
  150.      
  151.      /* macro to add to recio.h */
  152.      #define rgetb(rp) (rbgetb((rp), 2))
  153.  
  154.  
  155.  
  156. 3.0 DEVELOPMENT NOTES
  157.  
  158. 3.1 fgets (Microsoft C 5.1)
  159.  
  160. Previous notes of mine indicate that Microsoft's fgets function does not 
  161. work correctly when it reads a line of text that consists of only a newline.  
  162. However this can be worked around by first setting the string buffer to an 
  163. empty string.  You will need to test this if you plan on retaining the 
  164. newline.  The fgets function is used twice in the rgetrec function.  If 
  165. porting to Microsoft C, you may need to implement this fix:
  166.  
  167.      *rrecs(rp) = '\0';  /* just prior to the first fgets */
  168.      *str = '\0';        /* just prior to the second fgets */
  169.  
  170. 3.2 fopen (Borland C 3.1)
  171.  
  172. fopen() calls __openfp() calls open().  Borland's "Library Reference" 
  173. documents error numbers for open(), but not for fopen().  These error
  174. numbers are ENOENT, EMFILE, EACCES, and EINVACC.  Because ropen() screens 
  175. the access code, the EINVACC error will not occur from the recio library.
  176.  
  177. 3.3 strtol & strtoul (Borland C 3.1)
  178.  
  179. These functions stop consuming input once they overflow, setting ERANGE.  
  180. Hence endptr can point into the middle of a sequence of valid characters 
  181. having the expected form as given in ANSI X3.159-1989, Sections 4.10.1.5 
  182. and 4.10.1.6.  IMHO this characteristic is not in conformance with the 
  183. ANSI standard as endptr should only point to the first unrecognized 
  184. character or to the terminating null character.  Borland's strtod does 
  185. not have this problem.
  186.