home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-03-01 | 33.0 KB | 1,051 lines |
- Type : Documentation
- Subject : File_cl class (file objects)
- Author : Nat (FRANCE, excuse my loose English !)
- Version : 1.1 BETA
- Diffusion : Unrestricted
- Last version downloadable from :
- The Temple of Software BBS (FRANCE)
- File Area : C++ classes association
- Modem MicroCom QX up to 9600bps
- (33) 49837518
-
-
- Description :
- - This class permits file manipulation : one object/one physic file;
- one physic file/one object.
- - Simultaneously open files limited by the least value of :
- * Compiler library (stdio.h slots)
- Class methods use standard functions fopen(), fclose() ...
- * MAXFIL_OPEN #define value of the class.
- User of the class cannot modify it.
- * Operating system configuration (for example FILES under MS-DOS)
- * Application : user of the class can limit class access to slots.
- Method setMaxFilesOpen(int)
- In order to enforce portability I have not implemented "tricks"
- designated to bypass the limited (20) handles of the compiler's library
- - Amount of simultaneously active objects only limited by available core.
- - List of physic files maintained open optimized according to access
- frequency. Class housekeeping methods aim at maintaining open as long as
- possible the physic files most frequently accessed to.
- - Read/write operations order indifferent. I/O methods automatically open
- files if needed and only insert the necessary fseeks() calls between
- two distinct fread() and fwrite()
- - Only useful fseek() calls passed to the operating system
- - Smart DEBUGGING mode
- - Standard library-like prototypes
- - Use of standard type FILE permitted
- - Buffer optimisation method.
- - Core furnishment method through virtually closing physic files, thus
- releasing buffers
- - Special features :
- - Actual destruction : data erasure through writing
- - File cutting
- - File size increase
- - Stock features :
- unsigned long pascal crc_32(const unsigned char *p, unsigned int n, unsigned long crc = 0xFFFFFFFFL);
- Returns the 32-bit CCITT CRC
- (Thanks to JCD)
-
- void strcpyNameFile(char *dst, const char *nom);
- Builds the complete physic file pathname
- WARNING : does not process correctly expressions containing ".."
-
- char getCrtDrive(void);
- Returns the default drive letter
-
- char chDrive(char drive);
- Arg. : an uppercase letter
- Changes the default drive
-
- char drExists(char drive);
- Arg. : an uppercase letter
- Return value indicates wether the drive exists (OK) or not (ERR)
-
-
-
- Installation :
- If the father directory of the Integrated Development Environment is
- C:\BORLANDC
- Copy DEFS.HPP to C:\BORLANDC\NAT\CLASSES
- Copy FILE.HPP to C:\BORLANDC\NAT\CLASSES\INCLUDE
- Copy *.LIB to C:\BORLANDC\NAT\CLASSES\LIB
-
- Usage :
- Class name : File_cl
-
- Include "FILE_CL.HPP" into your sources and link the associated library
- (xdcccNAT.LIB, where 'x' stands for the memory model (C, L or H); 'd' only
- present for debugging libraries and 'ccc' compiler code ("BOR" (Borland) or
- "ZOR" (Zortech))
-
- For each model two versions of the library exist :
- - debugging version
- - normal full-size version
- The second letter of the debugging libraries names is 'D'
- Example : LDBORNAT.LIB (Large model, debugging version, Borland compiler)
- When using a debugging library please :
- #define NAT_FILE_DEBUG 1
-
- An abort function is necessary, whose prototype is :
- void cdecl die(int err, const char *fmt, ...)
-
- You might want to use the following standard :
- void cdecl die(int err, const char *msg ...)
- {
- va_list arg;
-
- if (err)
- {
- fprintf(stderr, "\n\nERROR :\n");
- va_start(arg, msg);
- vfprintf(stderr, msg, arg);
- va_end(arg);
- while(kbhit()) // flushes keyboard buffer
- getch();
- puts("\nHit a key to continue ...");
- getch(); // thus the user cannot but read the error message
- }
- exit(err);
- }
-
- The abort function die() must not call any File_cl class methods
-
- In case of debugging version :
- Each explicit call to a method leaves a log in a debugging file.
- To ensure this you must :
- - #define NAT_FILE_DEBUG of FILE_CL.HPP to 1,
- - declare an entire (int) variable named dbg_depth
- The log indentation varies according to this value
- - declare a FILE pointer variable (for debugging file) named ficdbg
-
-
- Use of any file object must always be preceded by a call to the assign()
- method
- Example :
-
- static File_cl *fics[10];
-
- #define NAT_FILE_DEBUG 1 // 1 if debug, 0 if normal version
-
- #ifdef NAT_FILE_DEBUG // debugging mode
- // ficdbg : permits access to debugging file
-
- FILE *ficdbg;
-
- // dbg_depth : current indentation level in debugging file
- int dbg_depth=0;
- #endif
-
- void initialize(void)
- {
- char caca[16];
-
- #ifdef NAT_FILE_DEBUG // debugging mode
- ficdbg=fopen("DEBUG.DBG", "wt");
- if (ficdbg==NULL)
- die(4, "Access to debugging file impossible");
- #endif
- for (int rep=0; rep<10; rep++)
- {
- if ((fic[rep]=new File_cl)==NULL)
- exit(4);
- if (fics[rep]->assign(itoa(rep, caca, 10), "r")==ERR) // assignations
- exit(5);
- }
- // file objects "fics" ready for use
- }
-
- void main(void)
- {
- initialize();
-
- // program ...
-
- // end of the program
- // do not forget to delete all the allocated objects !
- for (int rep=0; rep<10; rep++)
- delete fic[rep];
- }
-
- WARNING : assign() (in access mode "w") deletes existing files without
- checking. Please use access() before assign()
-
- As soon as the file object has been "assigned" (method assign()) it can be
- freely accessed to.
-
-
- In some cases you have to temporary virtually close one class File_cl object
- by using forceClose() in order to open a standard FILE (fopen() or open())
- The argument of forceClose represents the number of file slots desired.
- forceClose() then returns actual number of slots released.
- Call forceClose(MAXFIL_OPEN) to virtually close all files.
- The virtually closed file objects remain processable through the File_cl
- class methods, which will then try to reopen the physic files.
-
- Avoid heavy use of standard type FILE since the simultaneous opening of too
- many FILEs is likely to cause a file slot saturation - the File_cl class
- would freeze since it cannot temporarily close them to reopen one of its
- instanciations - so please give up the FILE interface to physic files.
- forceClose() is furnished for simultaneous use of the File_cl class and
- extern proprietary FILE-related libraries
-
-
- TRICKS :
-
- - Regroup all initial I/O accesses and then call internFclose() in order to
- reduce the simultaneously open files.
-
- - Methods whose names and actions are similar to standard library functions
- provided by compilers return identical values.
- (Example : rename() returns 0 if there is no problem, -1 otherwise)
-
- - Trig delete (keyword) as soon as possible the destructor for objects which
- have since become useless
-
- - Be careful with infinite loops since it can crash the stack !
- Example :
- If end() calls Bye() and if the latter calls end(), in case of error
- during the execution of bye() system may hang ...
- Note : the debugging version is compiled with "check stack overflow"
-
- - Use every available means to optimize the class methods performances :
- quicken the file reopening, increase the amount of slots (file handles)
- Under MS-DOS use FASTOPEN, FILES, FCBS ...
-
- - Before a new object file is assigned (assign()) the File_cl class checks
- whether another object is accessing to the same physic file. In this case
- new assign() is denied.
- Theoretically, all the file objects are global variables in the I/O
- modules.
- Following is an example that illustrates one of the many causes of this
- apparent limitation :
- If two distinct objects O1 and O2 access to the same physic file, then,
- for instance, so what is File_cl supposed to do if the current offset of O1
- is 600 while O2 cuts (cut() method) the file at offset 300 ?
-
- This kind of problem is solved through the
- File_cl *whatFile_cl(const char *namefile) const;
- method.
- It returns a pointer on the file object implying the physic file named
- "namefile" (or NULL if any)
- - In case of an I/O error its code is memorized in the object. Use the
- getErrCod() method to obtain it.
- (0 : no error)
- - Do not modify the system VERIFY flag
- - If you add any new generic feature to this class please feel free to
- contact me
-
- By carefully studying the furnished source file (provided for example and
- test purposes) you will be able to exploit this class at its best.
-
-
- Because of the inherent nature of this class pay attention to the following :
- ============================================================================
- Never forget that the compiler automatically calls the destructors of
- automatic objects (local instanciations).
-
- Example :
- void foo()
- {
- File_cl nothing;
- char str[]="ZUT";
-
- if (nothing.assign("ESSAI", "w")==ERR)
- die(254, "Cannot open file");
- nothing.fwrite(str, 1, 3);
-
- /* at this point, before completing this function (foo()), a destructor is
- called for the object "nothing". It flushes the file buffers, closes the
- physic file and releases the core allocated for the "nothing" object.
- */
- }
-
- The ANSI norm doesn't comprise the 't' (TEXT) argument for file opening modes.
- The File_cl class only manipulates files in binary modes (no CR/LF to '\n'
- conversion)
-
- The private members (organic references and methods) detail is not available
- to the end user (you !)
-
- For optimization's sake some prototypes are "inline" and/or "pascal"
- Never mind.
-
- The "FILE_CL.HPP" file furnished contains only one private declaration :
- a char member encapsulating all actual members. Do not modify it !
- If you do, the sizeof() calculus ends up erroneous (spoiling "new" and
- "delete")
-
- The keyword "const", typed after some methods prototypes, indicates that
- the method modifies none of the object's members.
-
-
- Public methods :
- ****************
- File_cl();
- Constructor : automatic call
- Don't pay attention to it.
-
-
- void classVersion(int *major, int *minor);
- Indicates the version of the File_cl class used
- Note : ugly !
- But useful if File_cl becames a DLL and/or another thing like that ...
-
-
- File_cl(const File_cl&);
- Copy-initializer
- I know of nobody who can say how this method is supposed to work for a
- file-oriented class.
- Therefore I prohibited the use of the copy-initializer.
-
-
- char assign(const char *name, const char *mode, int sizebuf=4096, unsigned char flush_frequency=0);
- Assignation
- Required before access to physic file !
- File attributes must in allc ases permit write access (never assign() a
- read-only file, please use internChmod() first)
- Arguments :
-
- name : Name of the physic file
- Will be expanded in order to build a complete pathname (volume, rep...)
- This complete name will be kept in the file-object
-
- mode : Opening mode :
- r : read only
- w : éwrite only (if file exists it will be replaced)
- Add a '+' sign ("r+", "w+") to allow all access modes.
- This argument is NULL for temporary files (actual mode will be R/W)
-
- sizebuf : Size of the file buffer (in bytes). Allocated through setvbuf()
-
- flush_frequency : frequency of automatic flushes (expressed in number of
- write accesses)
- 0 : minimal
- 1 : maximal (after each access)
- No flush for files limited to read access !
-
-
- Avoid assigning the same object several times. Once processed by assign()
- objects must be processed by reinit() before being assigned once again.
- Examples (no return values tests)
- {
- file1.assign("ESSAI", "r");
- file1.assign("ZUT", "r"); // forbidden
- }
-
- {
- file1.assign("ESSAI", "r");
- file1.reinit();
- file1.assign("ZUT", "r"); // tolerated (thanks to reinit())
- }
-
- At run-time, when physic files are being reopened before access, the "r+"
- mode is set on by the class methods. Debugging library alone can deny illegal
- operations (for example any attempt at writing on a physic file open for
- read operations only), thus also forbidding direct manipulation of read/only
- system tagged files.
-
- Use a NULL "mode" argument for temporary files. In this case a name composed
- of TMPx.TMP (x numeric) and prefixed by "name" will be built.
-
- Value returned : OK (no problem) ou ERR (error)
- ERR can also mean that another File_cl object already concerns the physic
- file in question.
-
-
- void setAbortOnErr(char s);
- Depending on "s" (1 or 0) the class will or will not abort execution after
- the first I/O error detected
-
-
- char getAbortOnErr(void);
- Returns the AbortOnErr flag (see setAbortOnErr())
-
-
- void setUsrErrFct(void (*argusr_err)(const char *, const char*, ...));
- Specifies which user function will be called by File_cl in case of an error
- Arguments passed to the user function :
- "File_cl", "<name of the file>", "<err. msg / function number>"
- THIS METHOD WILL CHANGE SOON !
-
-
- char pascal reinit(void);
- Allows (and must precede) a reassignation.
- Can be called any time : properly closes the physic file.
- This can be dangerous since, in your code, the physic file to which an
- object is dedicated at a given location is harder to determine.
-
- It allows to solve some of the problems caused by a limited stack.
- For instance when an entire file group is concerned by several functions a
- mere global declaration of all the objects and reinit() accesses will do the
- job. Actually none of the function should call any of the others.
-
- Example (without error condition test) :
-
- File_cl fic_tmp;
-
- // increments first int values contained in FIL1 to FIL20 files
- void fct1(void)
- {
- char str[MAXPATH_Nat];
- int val;
-
- strcpy(str, "FIL");
- for (int rep=0; rep<20; rep++)
- {
- itoa(rep, &str[3], 10);
-
- /* actual status of fic_tmp unknown at this point.
- An assign() call could have been carried through.
- So reinit() must be called
- */
- fic_tmp.reinit();
- fic_tmp.assign(str, "w+");
- fic_tmp.fread(&val, sizeof(int), 1);
- val++;
- fic_tmp.fwrite(&val, sizeof(int), 1, 0);
- fic_tmp.fclose();
- }
- }
-
- // other fonctions of the same kind can also use fic_tmp
-
- Return : OK or ERR
-
-
-
- ERRCOD_T getErrCod(void);
- Returns the last error code (or 0)
-
-
- OFFSET_T length(size_t *reste=NULL, size_t size_elem=1);
- Returns the file size.
- length() returns size in bytes
- length(X) returns the integer number of elements (X specifies size in bytes)
- length(X, *Y) like length(X), but *Y remainder
- Note : forces an open call
- Returns -1 in case of an error
-
-
- int fseek(OFFSET_T, int whence, char real=0);
- Changes the current offset inside the file.
- This is only a logical change, actual system call will be issued just before
- an I/O operation.
- Arguments : like the standard library fseek()
- The "real" argument forces an actual opening
- Note : a SEEK_END argument forces the opening and flush of the file
-
-
- OFFSET_T tell(void) const;
- Returns the current offset
-
-
- size_t fread(void *ptr, size_t size, size_t n, OFFSET_T o=-1);
- Reads data
- If needed :
- - opens the physic file
- - issues the fseek call that might be needed between reads and writes
- Arguments and return values similar to standard library
- The last argument indicates the offset
- Warning : polymorphism might cause errors such as :
- fread(&variable, sizeof(variable), 0) // false !!
- the third argument (0) specifies the number of elements, not the offset
- Correct form is :
- fread(&variable, sizeof(variable), 1, 0) // OK !!
-
-
- size_t fwrite(void *ptr, size_t size, size_t n, OFFSET_T o=-1);
- Writes data
- If needed :
- - opens the physic file
- - issues the fseek call that might be needed between reads and writes
- Flushes the buffer (if necessary, see flush_frequency argument of assign())
- Arguments and return values similar to standard library
- The last argument indicates the offset
- Warning : polymorphism might cause errors such as :
- fwrite(&variable, sizeof(variable), 0) // false !!
- the third argument (0) specifies the number of elements, not the offset
- Correct form is :
- fwrite(&variable, sizeof(variable), 1, 0) // OK !!
-
-
- int fputc(int c, OFFSET_T=-1);
- Like standard library
-
-
- int fgetc(OFFSET_T=-1);
- Like standard library
-
-
- char flush(char ouvre=0);
- Flushes the file buffer
- Periodically called (depending on the "flush_frequency" of assign()) by
- methods of writing
- flush(1) forces the physic file open. Never mind !
- Returns : NO_OP if physic file closed, OK if normally flushed, ERR otherwise
-
-
- int flushAll(void);
- Flushes all File_cl objects
- Returns the number of open physic files
-
-
- int eof(void);
- Calls flush()
- Returns 0 if End Of File not reached
-
-
- int error(void) const;
- Returns 0 if no I/O error on the file
-
-
- ERRCOD_T getErrCod(void) const;
- Returns the extended error code (errno)
-
-
- int fclose(void);
- Closes the physic file (if not already closed)
- Rewinds physic file : fseek(0, SEEK_SET);
- Returns : see ::fclose() : 0 (OK), EOF (error)
-
-
- Control methods
- ***************
-
- const char *getName(void) const;
- Returns a const pointer to the complete physic file name
- WARNING : do not bypass "const" qualifier. It's a STRICTLY private object
- zone.
-
-
- char isWritable(void) const;
- Mode of opening control : returns 1 if file readable, 0 otherwise
-
-
- char isReadable(void) const;
- Mode of opening control : returns 1 if file writable, 0 otherwise
-
-
- int internFclose(void);
- Optimization method
- Closes the physic file (liberating the handler)
- Meant to be used when the probable number of accesses to many other files
- before the next access on this one is very high.
- Does not alter the logical state of the object at all (offset remains the
- same). The next I/O request will be normally processed, yet implying the
- physic file opening.
- Returns NO_OPS (file was closed before call), OK (file properly closed) or
- EOF (error)
- If any given File_cl object pointed becomes useless please call its
- destructor as soon as possible (explicit delete)
-
-
- void stayOpen(void);
- This optimization method forces the maintenance methods to keep physic files
- open as long as possible.
- Usage of this method should be limited to files that are very often used.
-
-
- char isOpen(void) const;
- Returns 1 if physic file open, else 0. It is an optimization method
- Permits a pseudo-"burst mode"
- Example :
-
- char ok[NB_FIL];
-
- /* For optimization purposes, writing in the open files should come first :
- in this case maintenance methods do not close any open handle
- */
- for (int rep=0; rep<NB_FIL; rep++)
- if (fic[rep].isOpen())
- {
- rien.fwrite("RIEN", 1, 4);
- ok[rep]=1;
- }
- else
- ok[rep]=0;
- // then the others ...
- for (rep=0; rep<NOMBRE_FICS; rep++)
- if (!ok[rep])
- {
- rien.fwrite("RIEN", 1, 4);
- ok[rep]=1;
- }
-
-
- void setBuf(int size_buf=0);
- Assigns a "size_buf" bytes buffer size
- Maximum 32000 bytes
- WARNING : This new buffer size will only take effect when the next opening
- occurs. setBuf() yet increases the probability of the physic file being
- closed by housekeeping methods (scheduling handles conflicts)
- In order, for this modification, to take effect immediately call
- internFclose()
- Buffer is allocated through setvbuf (_IOFBF mode)
-
-
- void maxBuf(char percent_ram=25);
- Maximizes the size of the allocated buffer
- Argument is expressed in percent of free core
-
-
- char minBuf(long recup_ram=10000000L);
- Allows you to free some of the core previously allocated to the file buffer
- Argument is expressed in number of bytes requested
- Returns OK, NO_OP (file was closed) or ERR (close() error)
-
-
- void setVerify(char c=1) {verify=c;}
- Triggers write-checking for this object.
- Strictly comparable to the VERIFY system flag, but improved : it is limited
- to the object
-
-
- char getVerify(void) const;
- Returns 0 (=> VERIFY off for this objet or 1 (VERIFY ON)
-
-
- int forceClose(int, char real_fclose=1);
- This liberates handles occupied by File_cl objects (for FILE struct use)
- Only closes the "this" as a last resort
- Argument : number of slots (handles) desired. Use MAXFIL_OPEN to close
- all File_cl accessed files
- Return : number of liberated handles
- Do not use the second argument (for the sake of simplification polymorphism
- is not used here)
-
-
- char setMaxFilesOpen(int x);
- Specifies the maximum number of files that can be simultaneously open by
- the class.
- Closes immediately all supernumerary handles (but objects concerned remain
- usable)
- When external libraries need additional slots, use this method to avoid
- frequent forceClose() calls
- Returns OK or ERR (argument too high or too low)
-
-
- char giveCore(unsigned long howmuch);
- Frees RAM
- A very stupid method (for the time being) that forces the closure of physic
- files (through forceClose() calls) in order to immediately free RAM
- (particularly buffers RAM)
- Argument is expressed in bytes
- Does not affect the logical state of objects (all of them remain accessible)
-
-
- File_cl *whatFile_cl(const char *namefile) const;
- Returns a flag to the File_cl object whose physic file name the same as in
- the argument or NULL if no File_cl assigned to the file.
- WARNING : for optimization purposes no automatic name expansion (does not
- call strcpyNameFile())
-
- Example:
- char tmp_nom[MAXPATH_Nat];
- unsigned int trouves=0;
- File_cl tmp_obj;
- strcpyNameFile(tmp_nom, "ESSAI");
- if (tmp_obj=whatFile_cl(tmp_nom, &trouves))!=NULL)
- printf("Object %s en %Fp\n", tmp_obj->getName(), tmp_obj);
- else
- puts("No File_cl object for file ESSAI");
-
-
-
- High level methods
- ******************
-
- int internChmod(const char *path, char func, int attr);
- Like std _chmod()
-
-
- void setDriveVerify(char drive, char verif=1);
- Sets the VERIFY flag to "verif" (1 or 0) for all writable File_cl objects
- (present and to come) implying physic files located on drive "drive"
- Arguments :
- "drive" : [A, Z]
- "verif" : 1 (ON) or 0 (OFF)
-
-
- int unlink(char secure=0);
- Deletes physic file
- When equal to 1 the "secure" argument forces a call to writeGarbage() which
- rewrites on the data
- Return : 0 (OK), -1 (like standard library)
-
-
- void writeGarbage(OFFSET_T zone_size=-1);
- Writes garbage (data from the BIOS area : 0xF000)
- WARNING : the part of the file that will be written on begins at the current
- offset and its length is specified by "zone_size"
- Use default form to delete all file data
- Returns OK or ERR
-
-
- int rename(const char *);
- Renames the physic file
- Returns : -1 (error), else 0
- Note : forces file closure (internFclose() : no logical state modification)
-
-
- char getCRC32(unsigned long *crc32, OFFSET_T off=0, OFFSET_T len=0);
- Calculates the CCITT 32-bit CRC of the zone starting at offset "off" and
- which length is "len" bytes
- By default : off=0, len=file size
- Returns ERR (access error, buffer allocation error, "len"=0) ...
- WARNING : ERR may signify that this method can not restore the original file
- offset
- Places calculated CRC, if everything OK, in *crc32
- Does not affect the file state
- Thanks to Jean-Christophe Deschamps (fast CRC calculation routine)
-
-
- char copy(const char *newname, OFFSET_T start=0, OFFSET_T len=0);
- Copies the file in a new file named "newname". The zone copied begins
- at "start" offset (default 0) and is "len"-byte long.
- Returns OK, NO_OP (file "newname" already exists) or ERR
- WARNING : offset modified
-
-
- char copy(File_cl *dst, OFFSET_T start=0, OFFSET_T len=0);
- Copies the file in File_cl pointed by "dst".
- The zone copied begins at "start" offset (default 0) and is "len"-byte long.
- Target file is modified from its current offset
- Returns OK or ERR
- WARNING : offsets modified
-
-
- char compare(File_cl *other, OFFSET_T *first_dif, OFFSET_T start1=0, OFFSET_T start2=0, OFFSET_T len=0);
- Compares two sections of files
- Returns ERR (error), OK (identical content) or NO_OP (differences found)
- If the method returns NO_OP (unidentical contents) the OFFSET_T value
- pointed by "first_dif" will be the offset (from the beginning of the zone)
- of the first distinct byte.
- If the method returns ERR various errors may have occurred :
- - at least one of the files does not contain enough data
- Wrong arguments :
- ((size of file "this")-start1)<=0 => *first_dif=-2
- ((size of file "this")-start1)<len => *first_dif=-3
- ((size of file "other")-start2)<len => *first_dif=-4
-
- - Read error
- *first_diff=-5
-
-
- char move(const char *newname);
- Moves file
- Returns OK, NO_OP or ERR (see copy() and rename() methods)
- Strategy :
- This method first tries to call rename() (if "newname" belongs to the same
- volume)
- Otherwise (or if rename() cannot be done) calls copy() and then unlink()
-
-
- char cut(OFFSET_T where=-1, char secure=0);
- Cuts off file at the offset "where"
- If "secure" equals 1, data to be cut are processed by writeGarbage()
- Returns OK or ERR
-
-
- ~File_cl(void);
- Standard destructor
- Closes automatically the physic file
- Unlinks automatically temporary files
- WARNING : no error code returned (it's C++, not C !)
-
-
-
-
- Other functions
- ***************
-
-
- unsigned long pascal crc_32(const unsigned char *p, unsigned int n, unsigned long crc = 0xFFFFFFFFL);
- Returns the 32-bit CCITT CRC
- (Thanks to JCD)
-
- void strcpyNameFile(char *dst, const char *nom);
- Builds the complete physic file pathname
- WARNING : does not process correctly the expressions containing ".."
-
-
-
- char getCrtDrive(void);
- Returns the default drive letter
-
- char chDrive(char drive);
- Arg. : an uppercase letter
- Changes the default drive
-
- char drExists(char drive);
- Arg. : an uppercase letter
- Return value indicates wether the drive exists (OK) or not (ERR)
-
-
-
- I integrate the excellent match() function, from "SMATCH" package.
- Prototype is :
- /*
- int match: evaluates a *ix style pattern vs. a null terminated string.
- returns: 0 - match is good
- nonzero - match is not good
- */
-
- int match(char *pat, char *text);
-
-
- Parts of the original documentation follows :
-
- ========================
- SMATCH: a *IX compatible wildcard parser
- By Stan Adermann, 70721,17
-
- I was working on a database package recently, when I came to the
- decision that using the *ix wildcard system would be an extremely flexible
- way of retrieving records or making printouts, i.e. [A-E]* to print all
- names starting with A,B,C,D,E. (Certainly not an original thought.)
- Rather than reinvent the wheel, I looked on Compu$pend to find that a Mr.
- J. Kercheval had uploaded the source code I needed only days before. (My
- thanks to him. I was not familiar enough with the rules of *ix parsing to
- write one out of my skull.) When I read his comments about other routines
- being overly recursive or buggy, I sympathized...right up until I saw that
- he used recursion as well.
- I wondered, "Why recurse at all?" Certainly recursion is a valid way
- to do this, but by my own preference, I tend to avoid recursion if at all
- possible. My reasoning is that any recursive function has the ability to
- run amok and overflow memory, especially on smaller systems, unless you
- place limits. If you place limits, you run the risk of actually running
- into those limits, with the end result being a program failure or
- limitation that would not otherwise be necessary. Granted, in this case
- that is about as likely as the Pope using a condom, but as I said, this is
- a personal preference.
- Well, the thought of writing the same program non-recursively was stuck
- in my head, and I knew that I wouldn't sleep or eat until I had done it,
- so here it is. Not better, not worse, just different. Speedwise, SMATCH
- is equally as fast as Kercheval's MATCH. Sizewise, my program compiles
- about 130 bytes longer. Functionally speaking the programs have only two
- differences:
- 1. SMATCH allows patterns with no wildcards.
- 2. SMATCH supports the '+' (one or more) wildcard.
-
- I compiled using Microsoft C 6.0a, and the following command line:
- CL /AT /Ox /D TEST smatch.c -link /NOD:slibce+slibcer
- The same command line will also work for Kercheval's MATCH.C
-
- I have also borrowed Kercheval's MATCHTST.BAT to test my code, adding a
- few lines to test the '+' character.
-
- This code is public domain.
-
- The rules are:
- * matches any sequence of characters, including no characters
- * = "", "ABC", "ABCFRED"
- + matches any sequence of characters, but requires one character
- + = "A", "ABCDEFA"
- + != ""
- ? matches any one character
- ? = "A", "B", "C", "1"
- ? != "AB", "", "FRED"
- [] matches a single character from specified set.
- [aeioub-d] = "a", "b", "c", "d", "e", "i"
- [aeioub-d] != "f", "r", "t", "ap"
-
- To use one of the wildcards as a character, preceed it with a '\', i.e.
- \* \? \[ \] \\
-
- ========================
-
- Thanks Mister Adermann !
-
-
-
- Debugging library specific methods
- **********************************
-
- unsigned long status(char complete=1) const;
- Logical status of the object and class is printed in debugging file
- Returns the peak number of slots used (files actually open simultaneously)
-
-
- unsigned long getNbOpensTot(void) const;
- Returns the total number of opening calls issued (by the maintenance
- methods)
- Favors optimization : for a given environment the least value is the best
-
-
-
- Proposed debugging function :
- Through this function, your functions are able to share the debugging file
- with the class
- It leaves a message in the debugging file, preceded by the number of ticks elapsed since the
- execution began
- Uses dbg_depth
- Please use the Dbg_fct_fin macro to decrement the indentation index
-
- void debug(const char *fct, const char *fmt, ...)
- {
- va_list arg;
-
- if (ficdbg==NULL)
- return;
- dbg_depth++;
- for (int rep=0; rep<dbg_depth; rep++)
- ::fputc(' ', ficdbg);
- ::fprintf(ficdbg, "%ld %s ", clock(), fct);
- va_start(arg, fmt);
- ::vfprintf(ficdbg, fmt, arg);
- va_end(arg);
- ::fprintf(ficdbg, "\n");
- if (ferror(ficdbg))
- die(255, "Cannot write in debugging file");
- ::flushall();
- }
-
-
- Ideal structure of programs using this class :
- **********************************************
-
- Declarations module
- <must declare all File_cl objects>
-
- Main module
- <extern declarations>
- <die(int err, const char *msg ...) function implementation>
- <In case of debugging :
- FILE ficdbg
- int dbg_depth=0
- fopen()) of debugging file ficdbg
-
-
- Example :
- =========
-
- File_cl fic;
-
- #ifndef NDEBUG
- FILE *ficdbg;
- int dbg_depth=0;
- #endif
-
- void cdecl die(int err, const char *msg ...)
- {
- va_list arg;
-
- if (err)
- {
- fprintf(stderr, "\n\nERROR :\n");
- va_start(arg, msg);
- vfprintf(stderr, msg, arg);
- va_end(arg);
- while(kbhit()) // flushes keyboard buffer
- getch();
- puts("\nHit a key to continue ...");
- getch(); // thus the user cannot but read the error message
- }
- exit(err);
- }
-
- int cdecl main(void)
- {
- // Init
- File_cl fic;
-
- #ifndef NDEBUG
- ficdbg=fopen("DEBUG.DBG", "wt");
- if (ficdbg==NULL)
- die(4, "Cannot open debugging file");
- #endif
- if (fic.assign("ESSAI.TMP", "w+")!=OK)
- die(5, "cannot open file");
-
- <misc. processes>
-
- #ifdef NAT_FILE_DEBUG
- printf("\n -------->\nPeak number of files simultaneously open : %lu\nNumber of open calls : %lu\n", fic.status(), fic.getNbOpens_tot());
- #endif
- fclose(ficdbg);
- die(0, "BYE");
- }
-
-
-
- NOTES :
- *******
-
- - If you wish to use one error function for each file please use switch()
-
- - The furnished header file (FILE_CL.HPP) might contain several undocumented
- prototypes of methods. I strongly advise you NOT TO USE THEM !
-
- - This is a beta test version. Yet, future versions will be as compatible with
- this version as can be
-
- - If the relative slowness of the debugging version bothers you, please
- understand that they have not only been compiled with all checking pragmas
- on (check stack overflow, optimize for size ...) but also that much of the
- code is only meant to check the integrity of the environment and objects !
- You will get the picture when you will know that the normal version runs
- almost two times faster, manipulates objects that are 25% smaller and
- itself occupies only about 70% of the core needed by the debugging version.
-
- - How does the following sound :
- void strategy(char);
- Configures the type of handle conflict management : this is the kind of
- action that the maintenance methods try when reopening a physic file implies
- closing another.
-
- Argument :
- 0 : least employed files closed in priority
- 1 : most employed files closed in priority
-
- Any comments ?
-
- - After thinking about it over and over I thing that I am wrong to propose
- methods whose return values agree to ANSI specifications.
- Example : rename() could also return OK, NO_OP or ERR instead of the plain
- 0 or -1 !
- The day we agree on the decision to be made, I will design a powerful
- procedure of I/O errors control.
- Any comments ?
-
-
- - To increase the maximum number of simultaneously open files :
- * adapt the compiler libraries (stdio.h slots : _NFILES)
- * order a more effective File_cl class version
- (with a higher MAXFIL_OPEN value)
- * if possible, increase OS parameters (FILES under MS-DOS)
- * check usage of setMaxFilesOpen() method
-
-
-
- Versions :
- Date format : YYMMDD
- Value between parenthesis indicates version returned by classVersion method
-
- 920201 First beta version
-
- ---
-
-
- 920301 Second beta version (0.1)
-
- New methods :
- classVersion, internChmod
-
- New function :
- match
-
- ---
-
-
-
-
-
- Feel free to contact me.
- I can be reached at BBS "The Temple of Software" (in France, tel.
- (33) 49837518, user "Nat") or, by mail :
- Nat MAKAREVITCH
- 22, rue Voltaire
- 92000 NANTERRE
- FRANCE
-