home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / cprog / file_cl.zip / FILE_CL.DOC < prev    next >
Text File  |  1992-03-01  |  34KB  |  1,051 lines

  1. Type : Documentation
  2. Subject : File_cl class (file objects)
  3. Author : Nat (FRANCE, excuse my loose English !)
  4. Version : 1.1 BETA
  5. Diffusion : Unrestricted
  6. Last version downloadable from :
  7. The Temple of Software BBS (FRANCE)
  8. File Area : C++ classes association
  9. Modem MicroCom QX up to 9600bps
  10. (33) 49837518
  11.  
  12.  
  13. Description :
  14. - This class permits file manipulation : one object/one physic file;
  15.     one physic file/one object.
  16. - Simultaneously open files limited by the least value of :
  17.      * Compiler library (stdio.h slots)
  18.          Class methods use standard functions fopen(), fclose() ...
  19.      * MAXFIL_OPEN #define value of the class.
  20.          User of the class cannot modify it.
  21.      * Operating system configuration (for example FILES under MS-DOS)
  22.      * Application : user of the class can limit class access to slots.
  23.          Method setMaxFilesOpen(int)
  24.     In order to enforce portability I have not implemented "tricks"
  25.     designated to bypass the limited (20) handles of the compiler's library
  26. - Amount of simultaneously active objects only limited by available core.
  27. - List of physic files maintained open optimized according to access
  28.     frequency. Class housekeeping methods aim at maintaining open as long as
  29.     possible the physic files most frequently accessed to.
  30. - Read/write operations order indifferent. I/O methods automatically open
  31.     files if needed and only insert the necessary fseeks() calls between
  32.     two distinct fread() and fwrite()
  33. - Only useful fseek() calls passed to the operating system
  34. - Smart DEBUGGING mode
  35. - Standard library-like prototypes
  36. - Use of standard type FILE permitted
  37. - Buffer optimisation method.
  38. - Core furnishment method through virtually closing physic files, thus
  39.     releasing buffers
  40. - Special features :
  41.     - Actual destruction : data erasure through writing
  42.     - File cutting
  43.     - File size increase
  44. - Stock features :
  45.     unsigned long pascal crc_32(const unsigned char *p, unsigned int n, unsigned long crc = 0xFFFFFFFFL);
  46.      Returns the 32-bit CCITT CRC
  47.      (Thanks to JCD)
  48.  
  49.     void strcpyNameFile(char *dst, const char *nom);
  50.      Builds the complete physic file pathname
  51.      WARNING : does not process correctly expressions containing ".."
  52.  
  53.     char getCrtDrive(void);
  54.      Returns the default drive letter
  55.  
  56.     char chDrive(char drive);
  57.      Arg. : an uppercase letter
  58.      Changes the default drive
  59.  
  60.     char drExists(char drive);
  61.      Arg. : an uppercase letter
  62.      Return value indicates wether the drive exists (OK) or not (ERR)
  63.  
  64.  
  65.  
  66. Installation :
  67. If the father directory of the Integrated Development Environment is
  68. C:\BORLANDC
  69. Copy DEFS.HPP to C:\BORLANDC\NAT\CLASSES
  70. Copy FILE.HPP to C:\BORLANDC\NAT\CLASSES\INCLUDE
  71. Copy *.LIB to C:\BORLANDC\NAT\CLASSES\LIB
  72.  
  73. Usage :
  74. Class name : File_cl
  75.  
  76. Include "FILE_CL.HPP" into your sources and link the associated library
  77. (xdcccNAT.LIB, where 'x' stands for the memory model (C, L or H); 'd' only
  78. present for debugging libraries and 'ccc' compiler code ("BOR" (Borland) or
  79. "ZOR" (Zortech))
  80.  
  81. For each model two versions of the library exist :
  82.  - debugging version
  83.  - normal full-size version
  84. The second letter of the debugging libraries names is 'D'
  85. Example : LDBORNAT.LIB (Large model, debugging version, Borland compiler)
  86. When using a debugging library please :
  87. #define NAT_FILE_DEBUG 1
  88.  
  89. An abort function is necessary, whose prototype is :
  90. void cdecl die(int err, const char *fmt, ...)
  91.  
  92. You might want to use the following standard :
  93. void cdecl die(int err, const char *msg ...)
  94. {
  95.     va_list arg;
  96.  
  97.     if (err)
  98.         {
  99.         fprintf(stderr, "\n\nERROR :\n");
  100.         va_start(arg, msg);
  101.         vfprintf(stderr, msg, arg);
  102.         va_end(arg);
  103.         while(kbhit())    // flushes keyboard buffer
  104.             getch();
  105.         puts("\nHit a key to continue ...");
  106.         getch();    // thus the user cannot but read the error message
  107.         }
  108.     exit(err);
  109. }
  110.  
  111. The abort function die() must not call any File_cl class methods
  112.  
  113. In case of debugging version :
  114. Each explicit call to a method leaves a log in a debugging file.
  115. To ensure this you must :
  116. - #define NAT_FILE_DEBUG of FILE_CL.HPP to 1,
  117. - declare an entire (int) variable named dbg_depth
  118.     The log indentation varies according to this value
  119. - declare a FILE pointer variable (for debugging file) named ficdbg
  120.  
  121.  
  122. Use of any file object must always be preceded by a call to the assign()
  123. method
  124. Example :
  125.  
  126. static File_cl *fics[10];
  127.  
  128. #define NAT_FILE_DEBUG 1 // 1 if debug, 0 if normal version
  129.  
  130. #ifdef NAT_FILE_DEBUG    // debugging mode
  131. // ficdbg : permits access to debugging file
  132.  
  133. FILE *ficdbg;
  134.  
  135. // dbg_depth : current indentation level in debugging file
  136. int dbg_depth=0;
  137. #endif
  138.  
  139. void initialize(void)
  140. {
  141.     char caca[16];
  142.  
  143. #ifdef NAT_FILE_DEBUG    // debugging mode
  144.     ficdbg=fopen("DEBUG.DBG", "wt");
  145.     if (ficdbg==NULL)
  146.         die(4, "Access to debugging file impossible");
  147. #endif
  148.     for (int rep=0; rep<10; rep++)
  149.         {
  150.         if ((fic[rep]=new File_cl)==NULL)
  151.             exit(4);
  152.         if (fics[rep]->assign(itoa(rep, caca, 10), "r")==ERR)    // assignations
  153.             exit(5);
  154.         }
  155. // file objects "fics" ready for use
  156. }
  157.  
  158. void main(void)
  159. {
  160.     initialize();
  161.  
  162. // program ...
  163.  
  164. // end of the program
  165. // do not forget to delete all the allocated objects !
  166.     for (int rep=0; rep<10; rep++)
  167.         delete fic[rep];
  168. }
  169.  
  170. WARNING : assign() (in access mode "w") deletes existing files without
  171. checking. Please use access() before assign()
  172.  
  173. As soon as the file object has been "assigned" (method assign()) it can be
  174. freely accessed to.
  175.  
  176.  
  177. In some cases you have to temporary virtually close one class File_cl object
  178. by using forceClose() in order to open a standard FILE (fopen() or open())
  179. The argument of forceClose represents the number of file slots desired.
  180. forceClose() then returns actual number of slots released.
  181. Call forceClose(MAXFIL_OPEN) to virtually close all files.
  182. The virtually closed file objects remain processable through the File_cl
  183. class methods, which will then try to reopen the physic files.
  184.  
  185. Avoid heavy use of standard type FILE since the simultaneous opening of too
  186. many FILEs is likely to cause a file slot saturation  - the File_cl class
  187. would freeze since it cannot temporarily close them to reopen one of its
  188. instanciations - so please give up the FILE interface to physic files.
  189. forceClose() is furnished for simultaneous use of the File_cl class and
  190. extern proprietary FILE-related libraries
  191.  
  192.  
  193. TRICKS :
  194.  
  195. - Regroup all initial I/O accesses and then call internFclose() in order to
  196.     reduce the simultaneously open files.
  197.  
  198. - Methods whose names and actions are similar to standard library functions
  199.     provided by compilers return identical values.
  200.     (Example : rename() returns 0 if there is no problem, -1 otherwise)
  201.  
  202. - Trig delete (keyword) as soon as possible the destructor for objects which
  203.     have since become useless
  204.  
  205. - Be careful with infinite loops since it can crash the stack !
  206.     Example :
  207.     If end() calls Bye() and if the latter calls end(), in case of error
  208.     during the execution of bye() system may hang ...
  209.     Note : the debugging version is compiled with "check stack overflow"
  210.  
  211. -    Use every available    means to optimize the class methods performances :
  212.     quicken the file reopening, increase the amount of slots (file handles)
  213.     Under MS-DOS use FASTOPEN, FILES, FCBS ...
  214.  
  215. - Before a new object file is assigned (assign()) the File_cl class checks
  216.     whether another object is accessing to the same physic file. In this case
  217.     new assign() is denied.
  218.     Theoretically, all the file objects are global variables in the I/O
  219.     modules.
  220.     Following is an example that illustrates one of the many causes of this
  221.     apparent limitation :
  222.      If two distinct objects O1 and O2 access to the same physic file, then,
  223.      for instance, so what is File_cl supposed to do if the current offset of O1
  224.      is 600 while O2 cuts (cut() method) the file at offset 300 ?
  225.  
  226.     This kind of problem is solved through the
  227.     File_cl *whatFile_cl(const char *namefile) const;
  228.     method.
  229.     It returns a pointer on the file object implying the physic file named
  230.     "namefile" (or NULL if any)
  231. - In case of an I/O error its code is memorized in the object. Use the
  232.     getErrCod() method to obtain it.
  233.     (0 : no error)
  234. - Do not modify the system VERIFY flag
  235. - If you add any new generic feature to this class please feel free to
  236.     contact me
  237.  
  238. By carefully studying the furnished source file (provided for example and
  239. test purposes) you will be able to exploit this class at its best.
  240.  
  241.  
  242. Because of the inherent nature of this class pay attention to the following :
  243. ============================================================================
  244. Never forget that the compiler  automatically calls the destructors of
  245. automatic objects (local instanciations).
  246.  
  247. Example :
  248. void foo()
  249. {
  250.  File_cl nothing;
  251.  char str[]="ZUT";
  252.  
  253.  if (nothing.assign("ESSAI", "w")==ERR)
  254.     die(254, "Cannot open file");
  255.  nothing.fwrite(str, 1, 3);
  256.  
  257. /* at this point, before completing this function (foo()), a destructor is
  258. called for the object "nothing". It flushes the file buffers, closes the
  259. physic file and releases the core allocated for the "nothing" object.
  260. */
  261. }
  262.  
  263. The ANSI norm doesn't comprise the 't' (TEXT) argument for file opening modes.
  264. The File_cl class only manipulates files in binary modes (no CR/LF to '\n'
  265. conversion)
  266.  
  267. The private members (organic references and methods) detail is not available
  268. to the end user (you !)
  269.  
  270. For optimization's sake some prototypes are "inline" and/or "pascal"
  271. Never mind.
  272.  
  273. The "FILE_CL.HPP" file furnished contains only one private declaration :
  274. a char member encapsulating all actual members. Do not modify it !
  275. If you do, the sizeof() calculus ends up erroneous (spoiling "new" and
  276. "delete")
  277.  
  278. The keyword "const", typed after some methods prototypes, indicates that
  279. the method modifies none of the object's members.
  280.  
  281.  
  282. Public methods :
  283. ****************
  284. File_cl();
  285.  Constructor : automatic call
  286.  Don't pay attention to it.
  287.  
  288.  
  289. void classVersion(int *major, int *minor);
  290. Indicates the version of the File_cl class used
  291. Note : ugly !
  292. But useful if File_cl becames a DLL and/or another thing like that ...
  293.  
  294.  
  295. File_cl(const File_cl&);
  296.  Copy-initializer
  297.  I know of nobody who can say how this method is supposed to work for a
  298.  file-oriented class.
  299.  Therefore I prohibited the use of the copy-initializer.
  300.  
  301.  
  302. char assign(const char *name, const char *mode, int sizebuf=4096, unsigned char flush_frequency=0);
  303.  Assignation
  304.  Required before access to physic file !
  305.  File attributes must in allc ases permit write access (never assign() a
  306.  read-only file, please use internChmod() first)
  307.  Arguments :
  308.  
  309.  name : Name of the physic file
  310.                 Will be expanded in order to build a complete pathname (volume, rep...)
  311.                 This complete name will be kept in the file-object
  312.  
  313.  mode : Opening mode :
  314.                 r : read only
  315.                 w : éwrite only (if file exists it will be replaced)
  316.                 Add a '+' sign ("r+", "w+") to allow all access modes.
  317.                 This argument is NULL for temporary files (actual mode will be R/W)
  318.  
  319.  sizebuf : Size of the file buffer (in bytes). Allocated through setvbuf()
  320.  
  321.  flush_frequency : frequency of automatic flushes (expressed in number of
  322.                                      write accesses)
  323.                                      0 : minimal
  324.                                      1 : maximal (after each access)
  325.                                      No flush for files limited to read access !
  326.  
  327.  
  328. Avoid assigning the same object several times. Once processed by assign()
  329. objects must be processed by reinit() before being assigned once again.
  330. Examples (no return values tests)
  331. {
  332. file1.assign("ESSAI", "r");
  333. file1.assign("ZUT", "r");    // forbidden
  334. }
  335.  
  336. {
  337. file1.assign("ESSAI", "r");
  338. file1.reinit();
  339. file1.assign("ZUT", "r");    // tolerated (thanks to reinit())
  340. }
  341.  
  342. At run-time, when physic files are being reopened before access, the "r+"
  343. mode is set on by the class methods. Debugging library alone can deny illegal
  344. operations (for example any attempt at writing on a physic file open for
  345. read operations only), thus also forbidding direct manipulation of read/only
  346. system tagged files.
  347.  
  348. Use a NULL "mode" argument for temporary files. In this case a name composed
  349. of TMPx.TMP (x numeric) and prefixed by "name" will be built.
  350.  
  351. Value returned : OK (no problem) ou ERR (error)
  352. ERR can also mean that another File_cl object already concerns the physic
  353. file in question.
  354.  
  355.  
  356. void setAbortOnErr(char s);
  357. Depending on "s" (1 or 0) the class will or will not abort execution after
  358. the first I/O error detected
  359.  
  360.  
  361. char getAbortOnErr(void);
  362. Returns the AbortOnErr flag (see setAbortOnErr())
  363.  
  364.  
  365. void setUsrErrFct(void (*argusr_err)(const char *, const char*, ...));
  366. Specifies which user function will be called by File_cl in case of an error
  367. Arguments passed to the user function :
  368. "File_cl", "<name of the file>", "<err. msg / function number>"
  369. THIS METHOD WILL CHANGE SOON !
  370.  
  371.  
  372. char pascal reinit(void);
  373.  Allows (and must precede) a reassignation.
  374.  Can be called any time : properly closes the physic file.
  375.  This can be dangerous since, in your code, the physic file to which an
  376.  object is dedicated at a given location is harder to determine.
  377.  
  378.  It allows to solve some of the problems caused by a limited stack.
  379.  For instance when an entire file group is concerned by several functions a
  380.  mere global declaration of all the objects and reinit() accesses will do the
  381.  job. Actually none of the function should call any of the others.
  382.  
  383.  Example (without error condition test) :
  384.  
  385.  File_cl fic_tmp;
  386.  
  387.  // increments first int values contained in FIL1 to FIL20 files
  388.  void fct1(void)
  389.  {
  390.     char str[MAXPATH_Nat];
  391.     int val;
  392.  
  393.     strcpy(str, "FIL");
  394.     for (int rep=0; rep<20; rep++)
  395.         {
  396.         itoa(rep, &str[3], 10);
  397.  
  398. /* actual status of fic_tmp unknown at this point.
  399. An assign() call could have been carried through.
  400. So reinit() must be called
  401. */
  402.         fic_tmp.reinit();
  403.         fic_tmp.assign(str, "w+");
  404.         fic_tmp.fread(&val, sizeof(int), 1);
  405.         val++;
  406.         fic_tmp.fwrite(&val, sizeof(int), 1, 0);
  407.         fic_tmp.fclose();
  408.         }
  409.  }
  410.  
  411.  // other fonctions of the same kind can also use fic_tmp
  412.  
  413.  Return : OK or ERR
  414.  
  415.  
  416.  
  417. ERRCOD_T getErrCod(void);
  418.  Returns the last error code (or 0)
  419.  
  420.  
  421. OFFSET_T length(size_t *reste=NULL, size_t size_elem=1);
  422. Returns the file size.
  423.  length() returns size in bytes
  424.  length(X) returns the integer number of elements (X specifies size in bytes)
  425.  length(X, *Y) like length(X), but *Y remainder
  426.  Note : forces an open call
  427.  Returns -1 in case of an error
  428.  
  429.  
  430. int fseek(OFFSET_T, int whence, char real=0);
  431.  Changes the current offset inside the file.
  432.  This is only a logical change, actual system call will be issued just before
  433.  an I/O operation.
  434.  Arguments : like the standard library fseek()
  435.  The "real" argument forces an actual opening
  436.  Note : a SEEK_END argument forces the opening and flush of the file
  437.  
  438.  
  439. OFFSET_T tell(void) const;
  440.  Returns the current offset
  441.  
  442.  
  443. size_t fread(void *ptr, size_t size, size_t n, OFFSET_T o=-1);
  444.  Reads data
  445.  If needed :
  446.  - opens the physic file
  447.  - issues the fseek call that might be needed between reads and writes
  448.  Arguments and return values similar to standard library
  449.  The last argument indicates the offset
  450.  Warning : polymorphism might cause errors such as :
  451.  fread(&variable, sizeof(variable), 0)    // false !!
  452.  the third argument (0) specifies the number of elements, not the offset
  453.  Correct form is :
  454.  fread(&variable, sizeof(variable), 1, 0)    // OK !!
  455.  
  456.  
  457. size_t fwrite(void *ptr, size_t size, size_t n, OFFSET_T o=-1);
  458.  Writes data
  459.  If needed :
  460.  - opens the physic file
  461.  - issues the fseek call that might be needed between reads and writes
  462.  Flushes the buffer (if necessary, see flush_frequency argument of assign())
  463.  Arguments and return values similar to standard library
  464.  The last argument indicates the offset
  465.  Warning : polymorphism might cause errors such as :
  466.  fwrite(&variable, sizeof(variable), 0)    // false !!
  467.  the third argument (0) specifies the number of elements, not the offset
  468.  Correct form is :
  469.  fwrite(&variable, sizeof(variable), 1, 0)    // OK !!
  470.  
  471.  
  472. int fputc(int c, OFFSET_T=-1);
  473.  Like standard library
  474.  
  475.  
  476. int fgetc(OFFSET_T=-1);
  477.  Like standard library
  478.  
  479.  
  480. char flush(char ouvre=0);
  481.  Flushes the file buffer
  482.  Periodically called (depending on the "flush_frequency" of assign()) by
  483.  methods of writing
  484.  flush(1) forces the physic file open. Never mind !
  485.  Returns : NO_OP if physic file closed, OK if normally flushed, ERR otherwise
  486.  
  487.  
  488. int flushAll(void);
  489.  Flushes all File_cl objects
  490.  Returns the number of open physic files
  491.  
  492.  
  493. int eof(void);
  494.  Calls flush()
  495.  Returns 0 if End Of File not reached
  496.  
  497.  
  498. int error(void) const;
  499.  Returns 0 if no I/O error on the file
  500.  
  501.  
  502. ERRCOD_T getErrCod(void) const;
  503.  Returns the extended error code (errno)
  504.  
  505.  
  506. int fclose(void);
  507.  Closes the physic file (if not already closed)
  508.  Rewinds physic file : fseek(0, SEEK_SET);
  509.  Returns : see ::fclose() : 0 (OK), EOF (error)
  510.  
  511.  
  512. Control methods
  513. ***************
  514.  
  515. const char *getName(void) const;
  516.  Returns a const pointer to the complete physic file name
  517.  WARNING : do not bypass "const" qualifier. It's a STRICTLY private object
  518.  zone.
  519.  
  520.  
  521. char isWritable(void) const;
  522.  Mode of opening control : returns 1 if file readable, 0 otherwise
  523.  
  524.  
  525. char isReadable(void) const;
  526.  Mode of opening control : returns 1 if file writable, 0 otherwise
  527.  
  528.  
  529. int internFclose(void);
  530.  Optimization method
  531.  Closes the physic file (liberating the handler)
  532.  Meant to be used when the probable number of accesses to many other files
  533.  before the next access on this one is very high.
  534.  Does not alter the logical state of the object at all (offset remains the
  535.  same). The next I/O request will be normally processed, yet implying the
  536.  physic file opening.
  537.  Returns NO_OPS (file was closed before call), OK (file properly closed) or
  538.  EOF (error)
  539.  If any given File_cl object pointed becomes useless please call its
  540.  destructor as soon as possible (explicit delete)
  541.  
  542.  
  543. void stayOpen(void);
  544.  This optimization method forces the maintenance methods to keep physic files
  545.  open as long as possible.
  546.  Usage of this method should be limited to files that are very often used.
  547.  
  548.  
  549. char isOpen(void) const;
  550.  Returns 1 if physic file open, else 0. It is an optimization method
  551.  Permits a pseudo-"burst mode"
  552.  Example :
  553.  
  554.  char ok[NB_FIL];
  555.  
  556. /* For optimization purposes, writing in the open files should come first :
  557. in this case maintenance methods do not close any open handle
  558. */
  559.  for (int rep=0; rep<NB_FIL; rep++)
  560.      if (fic[rep].isOpen())
  561.          {
  562.          rien.fwrite("RIEN", 1, 4);
  563.          ok[rep]=1;
  564.          }
  565.      else
  566.          ok[rep]=0;
  567. // then the others ...
  568.  for (rep=0; rep<NOMBRE_FICS; rep++)
  569.      if (!ok[rep])
  570.          {
  571.          rien.fwrite("RIEN", 1, 4);
  572.          ok[rep]=1;
  573.          }
  574.  
  575.  
  576. void setBuf(int size_buf=0);
  577.  Assigns a "size_buf" bytes buffer size
  578.  Maximum 32000 bytes
  579.  WARNING : This new buffer size will only take effect when the next opening
  580.  occurs. setBuf() yet increases the probability of the physic file being
  581.  closed by housekeeping methods (scheduling handles conflicts)
  582.  In order, for this modification, to take effect immediately call
  583.  internFclose()
  584.  Buffer is allocated through setvbuf (_IOFBF mode)
  585.  
  586.  
  587. void maxBuf(char percent_ram=25);
  588.  Maximizes the size of the allocated buffer
  589.  Argument is expressed in percent of free core
  590.  
  591.  
  592. char minBuf(long recup_ram=10000000L);
  593.  Allows you to free some of the core previously allocated to the file buffer
  594.  Argument is expressed in number of bytes requested
  595.  Returns OK, NO_OP (file was closed) or ERR (close() error)
  596.  
  597.  
  598. void setVerify(char c=1) {verify=c;}
  599.  Triggers write-checking for this object.
  600.  Strictly comparable to the VERIFY system flag, but improved : it is limited
  601.  to the object
  602.  
  603.  
  604. char getVerify(void) const;
  605.  Returns 0 (=> VERIFY off for this objet or 1 (VERIFY ON)
  606.  
  607.  
  608. int forceClose(int, char real_fclose=1);
  609.  This liberates handles occupied by File_cl objects (for FILE struct use)
  610.  Only closes the "this" as a last resort
  611.  Argument : number of slots (handles) desired. Use MAXFIL_OPEN to close
  612.  all File_cl accessed files
  613.  Return : number of liberated handles
  614.  Do not use the second argument (for the sake of simplification polymorphism
  615.  is not used here)
  616.  
  617.  
  618. char setMaxFilesOpen(int x);
  619.  Specifies the maximum number of files that can be simultaneously open by
  620.  the class.
  621.  Closes immediately all supernumerary handles (but objects concerned remain
  622.  usable)
  623.  When external libraries need additional slots, use this method to avoid
  624.  frequent forceClose() calls
  625.  Returns OK or ERR (argument too high or too low)
  626.  
  627.  
  628. char giveCore(unsigned long howmuch);
  629.  Frees RAM
  630.  A very stupid method (for the time being) that forces the closure of physic
  631.  files (through forceClose() calls) in order to immediately free RAM
  632.  (particularly buffers RAM)
  633.  Argument is expressed in bytes
  634.  Does not affect the logical state of objects (all of them remain accessible)
  635.  
  636.  
  637. File_cl *whatFile_cl(const char *namefile) const;
  638.  Returns a flag to the File_cl object whose physic file name the same as in
  639.  the argument or NULL if no File_cl assigned to the file.
  640.  WARNING : for optimization purposes no automatic name expansion (does not
  641.  call strcpyNameFile())
  642.  
  643. Example:
  644. char tmp_nom[MAXPATH_Nat];
  645.  unsigned int trouves=0;
  646.  File_cl tmp_obj;
  647.  strcpyNameFile(tmp_nom, "ESSAI");
  648.  if (tmp_obj=whatFile_cl(tmp_nom, &trouves))!=NULL)
  649.     printf("Object %s en %Fp\n", tmp_obj->getName(), tmp_obj);
  650.  else
  651.     puts("No File_cl object for file ESSAI");
  652.  
  653.  
  654.  
  655. High level methods
  656. ******************
  657.  
  658. int internChmod(const char *path, char func, int attr);
  659.  Like std _chmod()
  660.  
  661.  
  662. void setDriveVerify(char drive, char verif=1);
  663.  Sets the VERIFY flag to "verif" (1 or 0) for all writable File_cl objects
  664.  (present and to come) implying physic files located on drive "drive"
  665.  Arguments :
  666.  "drive" : [A, Z]
  667.  "verif" : 1 (ON) or 0 (OFF)
  668.  
  669.  
  670. int unlink(char secure=0);
  671.  Deletes physic file
  672.  When equal to 1 the "secure" argument forces a call to writeGarbage() which
  673.  rewrites on the data
  674.  Return : 0 (OK), -1 (like standard library)
  675.  
  676.  
  677. void writeGarbage(OFFSET_T zone_size=-1);
  678.  Writes garbage (data from the BIOS area : 0xF000)
  679.  WARNING : the part of the file that will be written on begins at the current
  680.  offset and its length is specified by "zone_size"
  681.  Use default form to delete all file data
  682.  Returns OK or ERR
  683.  
  684.  
  685. int rename(const char *);
  686.  Renames the physic file
  687.  Returns : -1 (error), else 0
  688.  Note : forces file closure (internFclose() : no logical state modification)
  689.  
  690.  
  691. char getCRC32(unsigned long *crc32, OFFSET_T off=0, OFFSET_T len=0);
  692.  Calculates the CCITT 32-bit CRC of the zone starting at offset "off" and
  693.  which length is "len" bytes
  694.  By default : off=0, len=file size
  695.  Returns ERR (access error, buffer allocation error, "len"=0) ...
  696.  WARNING : ERR may signify that this method can not restore the original file
  697.  offset
  698.  Places calculated CRC, if everything OK, in *crc32
  699.  Does not affect the file state
  700.  Thanks to Jean-Christophe Deschamps (fast CRC calculation routine)
  701.  
  702.  
  703. char copy(const char *newname, OFFSET_T start=0, OFFSET_T len=0);
  704.  Copies the file in a new file named "newname". The zone copied begins
  705.  at "start" offset (default 0) and is "len"-byte long.
  706.  Returns OK, NO_OP (file "newname" already exists) or ERR
  707.  WARNING : offset modified
  708.  
  709.  
  710. char copy(File_cl *dst, OFFSET_T start=0, OFFSET_T len=0);
  711.  Copies the file in File_cl pointed by "dst".
  712.  The zone copied begins at "start" offset (default 0) and is "len"-byte long.
  713.  Target file is modified from its current offset
  714.  Returns OK or ERR
  715.  WARNING : offsets modified
  716.  
  717.  
  718. char compare(File_cl *other, OFFSET_T *first_dif, OFFSET_T start1=0, OFFSET_T start2=0, OFFSET_T len=0);
  719.  Compares two sections of files
  720.  Returns ERR (error), OK (identical content) or NO_OP (differences found)
  721.  If the method returns NO_OP (unidentical contents) the OFFSET_T value
  722.  pointed by "first_dif" will be the offset (from the beginning of the zone)
  723.  of the first distinct byte.
  724.  If the method returns ERR various errors may have occurred :
  725.      - at least one of the files does not contain enough data
  726.          Wrong arguments :
  727.             ((size of file "this")-start1)<=0   => *first_dif=-2
  728.             ((size of file "this")-start1)<len  => *first_dif=-3
  729.             ((size of file "other")-start2)<len => *first_dif=-4
  730.  
  731.      - Read error
  732.             *first_diff=-5
  733.  
  734.  
  735. char move(const char *newname);
  736.  Moves file
  737.  Returns OK, NO_OP or ERR (see copy() and rename() methods)
  738.  Strategy :
  739.  This method first tries to call rename() (if "newname" belongs to the same
  740.  volume)
  741.  Otherwise (or if rename() cannot be done) calls copy() and then unlink()
  742.  
  743.  
  744. char cut(OFFSET_T where=-1, char secure=0);
  745.  Cuts off file at the offset "where"
  746.  If "secure" equals 1, data to be cut are processed by writeGarbage()
  747.  Returns OK or ERR
  748.  
  749.  
  750. ~File_cl(void);
  751.  Standard destructor
  752.  Closes automatically the physic file
  753.  Unlinks automatically temporary files
  754.  WARNING : no error code returned (it's C++, not C !)
  755.  
  756.  
  757.  
  758.  
  759. Other functions
  760. ***************
  761.  
  762.  
  763. unsigned long pascal crc_32(const unsigned char *p, unsigned int n, unsigned long crc = 0xFFFFFFFFL);
  764.  Returns the 32-bit CCITT CRC
  765.  (Thanks to JCD)
  766.  
  767. void strcpyNameFile(char *dst, const char *nom);
  768.  Builds the complete physic file pathname
  769.  WARNING : does not process correctly the expressions containing ".."
  770.  
  771.  
  772.  
  773. char getCrtDrive(void);
  774.  Returns the default drive letter
  775.  
  776. char chDrive(char drive);
  777.  Arg. : an uppercase letter
  778.  Changes the default drive
  779.  
  780. char drExists(char drive);
  781.  Arg. : an uppercase letter
  782.  Return value indicates wether the drive exists (OK) or not (ERR)
  783.  
  784.  
  785.  
  786. I integrate the excellent match() function, from "SMATCH" package.
  787. Prototype is :
  788. /*
  789.      int match: evaluates a *ix style pattern vs. a null terminated string.
  790.             returns:   0 - match is good
  791.                              nonzero - match is not good
  792. */
  793.  
  794. int match(char *pat, char *text);
  795.  
  796.  
  797. Parts of the original documentation follows :
  798.  
  799. ========================
  800. SMATCH: a *IX compatible wildcard parser
  801. By Stan Adermann, 70721,17
  802.  
  803.      I was working on a database package recently, when I came to the
  804. decision that using the *ix wildcard system would be an extremely flexible
  805. way of retrieving records or making printouts, i.e. [A-E]* to print all
  806. names starting with A,B,C,D,E. (Certainly not an original thought.)
  807. Rather than reinvent the wheel, I looked on Compu$pend to find that a Mr.
  808. J. Kercheval had uploaded the source code I needed only days before.  (My
  809. thanks to him.  I was not familiar enough with the rules of *ix parsing to
  810. write one out of my skull.)  When I read his comments about other routines
  811. being overly recursive or buggy, I sympathized...right up until I saw that
  812. he used recursion as well.
  813.      I wondered, "Why recurse at all?"  Certainly recursion is a valid way
  814. to do this, but by my own preference, I tend to avoid recursion if at all
  815. possible.  My reasoning is that any recursive function has the ability to
  816. run amok and overflow memory, especially on smaller systems, unless you
  817. place limits.  If you place limits, you run the risk of actually running
  818. into those limits, with the end result being a program failure or
  819. limitation that would not otherwise be necessary.  Granted, in this case
  820. that is about as likely as the Pope using a condom, but as I said, this is
  821. a personal preference.
  822.      Well, the thought of writing the same program non-recursively was stuck
  823. in my head, and I knew that I wouldn't sleep or eat until I had done it,
  824. so here it is.  Not better, not worse, just different.  Speedwise, SMATCH
  825. is equally as fast as Kercheval's MATCH.  Sizewise, my program compiles
  826. about 130 bytes longer.  Functionally speaking the programs have only two
  827. differences:
  828.      1. SMATCH allows patterns with no wildcards.
  829.      2. SMATCH supports the '+' (one or more) wildcard.
  830.  
  831. I compiled using Microsoft C 6.0a, and the following command line:
  832.      CL /AT /Ox /D TEST smatch.c -link /NOD:slibce+slibcer
  833. The same command line will also work for Kercheval's MATCH.C
  834.  
  835. I have also borrowed Kercheval's MATCHTST.BAT to test my code, adding a
  836. few lines to test the '+' character.
  837.  
  838. This code is public domain.
  839.  
  840. The rules are:
  841.      * matches any sequence of characters, including no characters
  842.             * = "", "ABC", "ABCFRED"
  843.      + matches any sequence of characters, but requires one character
  844.             + = "A", "ABCDEFA"
  845.             + != ""
  846.      ? matches any one character
  847.             ? = "A", "B", "C", "1"
  848.             ? != "AB", "", "FRED"
  849.      [] matches a single character from specified set.
  850.             [aeioub-d] = "a", "b", "c", "d", "e", "i"
  851.             [aeioub-d] != "f", "r", "t", "ap"
  852.  
  853. To use one of the wildcards as a character, preceed it with a '\', i.e.
  854.      \*   \?   \[   \]   \\
  855.  
  856. ========================
  857.  
  858. Thanks Mister Adermann !
  859.  
  860.  
  861.  
  862. Debugging library specific methods
  863. **********************************
  864.  
  865. unsigned long status(char complete=1) const;
  866.  Logical status of the object and class is printed in debugging file
  867.  Returns the peak number of slots used (files actually open simultaneously)
  868.  
  869.  
  870. unsigned long getNbOpensTot(void) const;
  871.  Returns the total number of opening calls issued (by the maintenance
  872.  methods)
  873.  Favors optimization : for a given environment the least value is the best
  874.  
  875.  
  876.  
  877. Proposed debugging function :
  878. Through this function, your functions are able to share the debugging file
  879. with the class
  880. It leaves a message in the debugging file, preceded by the number of ticks elapsed since the
  881. execution began
  882. Uses dbg_depth
  883. Please use the Dbg_fct_fin macro to decrement the indentation index
  884.  
  885. void debug(const char *fct, const char *fmt, ...)
  886. {
  887.     va_list arg;
  888.  
  889.     if (ficdbg==NULL)
  890.         return;
  891.     dbg_depth++;
  892.     for (int rep=0; rep<dbg_depth; rep++)
  893.         ::fputc(' ', ficdbg);
  894.     ::fprintf(ficdbg, "%ld %s ", clock(), fct);
  895.     va_start(arg, fmt);
  896.     ::vfprintf(ficdbg, fmt, arg);
  897.     va_end(arg);
  898.     ::fprintf(ficdbg, "\n");
  899.     if (ferror(ficdbg))
  900.         die(255, "Cannot write in debugging file");
  901.     ::flushall();
  902. }
  903.  
  904.  
  905. Ideal structure of programs using this class :
  906. **********************************************
  907.  
  908. Declarations module
  909. <must declare all File_cl objects>
  910.  
  911. Main module
  912. <extern declarations>
  913. <die(int err, const char *msg ...) function implementation>
  914. <In case of debugging :
  915. FILE ficdbg
  916. int dbg_depth=0
  917. fopen()) of debugging file ficdbg
  918.  
  919.  
  920. Example :
  921. =========
  922.  
  923. File_cl fic;
  924.  
  925. #ifndef NDEBUG
  926. FILE *ficdbg;
  927. int dbg_depth=0;
  928. #endif
  929.  
  930. void cdecl die(int err, const char *msg ...)
  931. {
  932.     va_list arg;
  933.  
  934.     if (err)
  935.         {
  936.         fprintf(stderr, "\n\nERROR :\n");
  937.         va_start(arg, msg);
  938.         vfprintf(stderr, msg, arg);
  939.         va_end(arg);
  940.         while(kbhit())    // flushes keyboard buffer
  941.             getch();
  942.         puts("\nHit a key to continue ...");
  943.         getch();    // thus the user cannot but read the error message
  944.         }
  945.     exit(err);
  946. }
  947.  
  948. int cdecl main(void)
  949. {
  950. // Init
  951.     File_cl fic;
  952.  
  953. #ifndef NDEBUG
  954.     ficdbg=fopen("DEBUG.DBG", "wt");
  955.     if (ficdbg==NULL)
  956.         die(4, "Cannot open debugging file");
  957. #endif
  958.     if (fic.assign("ESSAI.TMP", "w+")!=OK)
  959.         die(5, "cannot open file");
  960.  
  961.         <misc. processes>
  962.  
  963. #ifdef NAT_FILE_DEBUG
  964.     printf("\n -------->\nPeak number of files simultaneously open : %lu\nNumber of open calls : %lu\n", fic.status(), fic.getNbOpens_tot());
  965. #endif
  966.     fclose(ficdbg);
  967.     die(0, "BYE");
  968. }
  969.  
  970.  
  971.  
  972. NOTES :
  973. *******
  974.  
  975. - If you wish to use one error function for each file please use switch()
  976.  
  977. - The furnished header file (FILE_CL.HPP) might contain several undocumented
  978.     prototypes of methods. I strongly advise you NOT TO USE THEM !
  979.  
  980. - This is a beta test version. Yet, future versions will be as compatible with
  981.     this version as can be
  982.  
  983. - If the relative slowness of the debugging version bothers you, please
  984.     understand that they have not only been compiled with all checking pragmas
  985.     on (check stack overflow, optimize    for size ...) but also that much of the
  986.     code is only meant to check the integrity of the environment and objects !
  987.     You will get the picture when you will know that the normal version runs
  988.     almost two times faster, manipulates objects that are 25% smaller and
  989.     itself occupies only about 70% of the core needed by the debugging version.
  990.  
  991. - How does the following sound :
  992. void strategy(char);
  993. Configures the type of handle conflict management : this is the kind of
  994. action that the maintenance methods try when reopening a physic file implies
  995. closing another.
  996.  
  997. Argument :
  998. 0 : least employed files closed in priority
  999. 1 : most employed files closed in priority
  1000.  
  1001. Any comments ?
  1002.  
  1003. - After thinking about it over and over I thing that I am wrong to propose
  1004.     methods whose return values agree to ANSI specifications.
  1005.     Example : rename() could also return OK, NO_OP or ERR instead of the plain
  1006.     0 or -1 !
  1007.     The day we agree on the decision to be made, I will design a powerful
  1008.     procedure of    I/O errors control.
  1009.     Any comments ?
  1010.  
  1011.  
  1012. - To increase the maximum number of simultaneously open files :
  1013.  * adapt the compiler libraries (stdio.h slots : _NFILES)
  1014.  * order a more effective File_cl class version
  1015.      (with a higher MAXFIL_OPEN value)
  1016.  * if possible, increase OS parameters (FILES under MS-DOS)
  1017.  * check usage of setMaxFilesOpen() method
  1018.  
  1019.  
  1020.  
  1021. Versions :
  1022. Date format : YYMMDD
  1023. Value between parenthesis indicates version returned by classVersion method
  1024.  
  1025. 920201 First beta version
  1026.  
  1027. ---
  1028.  
  1029.  
  1030. 920301 Second beta version (0.1)
  1031.  
  1032. New methods :
  1033. classVersion, internChmod
  1034.  
  1035. New function :
  1036. match
  1037.  
  1038. ---
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044. Feel free to contact me.
  1045. I can be reached at BBS "The Temple of Software" (in France, tel.
  1046. (33) 49837518, user "Nat") or, by mail :
  1047. Nat MAKAREVITCH
  1048. 22, rue Voltaire
  1049. 92000 NANTERRE
  1050. FRANCE
  1051.