version 1.0
Contents:
About this lib
How to use
Comments
When a program has to deal with a large amount of data's (sprites, maps, strings...), it is often useful to save those data's into external files and to load only what the prog needs. The problem we have is that the functions we need to manipulate those files (typically the ones from stdio.h) are a bit heavy, and they make the size of the prog grow significantly.
The aim of this lib is to provide "light" functions that are used on the same way as those from stdio.h. The difference is that there is no sophistiquated management of the opened files: these functions are only calling the different services of the 21h interrupt. Their size is thus quite smaller.
One can now use those "rewritten" functions in a prog instead of stdio.h, and the size of the prog will decrease by a few Kb's. Here is the list of those ones: fopen(), fclose(), fread(), fseek(), ftell(), fgetc(), fgets(), findfirst() and findnext(). They are now called cfopen(), cfclose(), cfread() etc in this lib. Note that cfread() is now able to write the file's data's to a far adress (e.g. you can copy the content of a file directly in a memzone without buffer), and that cfindfirst() works now correctly if you try to scan an empty drive.
The use of those functions is globally the same as those from stdio.h. You can also take a look at its documentation to see some examples of use.
All functions of this lib have a corresponding macro in casfiles.h. If you don't need some of them in your prog, you just have to comment the corresponding macros in the file and the compiler won't be able to see them, then you prog will be a bit smaller. e.g. if you don't need cfgetc() and cfgets(), you just have to comment those lines (do not delete them):
#define FUNC_CFGETC
#define FUNC_CFGETS
All functions return an error code that specifies if the operation has succeded or not. This value is equal to zero when everything worked correctly, or negative is some error was encountered. Those codes are also defined in the file casfiles.h.
Files can be opened with cfopen(). You have to pass it the complete path of the file (e.g. "L:\myfile.txt") and a "handle" that will be used to identify this file during the next operations. You can now access the content of the file by knowing its handle. When you don't need the file anymore, you have to close it with cfclose(). The handle will then become invalid.
#include "casfiles.h"
void main()
{
HANDLE myFile;
// The handle that identifies the file
if( cfopen("L:\\myfile.txt", myFile) == DONE )
// if the opening succeeded
{
...
// reading the content of the file
cfclose(myFile);
// closing
}
}
cfread() and cfcopy() are generally used to read the content of the file. You have to specify the address where the data's will be copied, the number of bytes to read, the location of the data's you want in the file (only if you're using cfcopy()) and naturally the handle of the file. cfread() read bytes from the current position, however cfcopy() will read bytes at the specified location. Note that cfread() is faster than cfcopy() since it doesn't have to deal with the position of the pointer, which increases automatically.
It is possible to directly write the content of a file into a memory zone. Don't forget that this operation isn't secured at all, and that you can lose all your memory data's if you don't copy the content of the file at a correct place!!
The position of the pointer in a file goes automatically forward when you read its content (except if you use cfcopy()). You can change this position to access data's at a certain place in a file, or get its current value. This can be done with the cfseek() and cftell() functions.
cfseek() is used to set the position of the pointer: you have to pass it the shifting to do, the relative position of this shifting, and the handle of the file. The relative position can be the beginning of the file (SEEK_SET), the current position (SEEK_CUR) or the end (SEEK_END).
cfseek(10, SEEK_SET, theFile);
// we are going 10 bytes after the beginning of the file
cfseek(-3, SEEK_CUR, theFile);
// we are now 7 bytes after the beginning
cftell() needs the integer in which it will save the current position of the pointer, and the handle. Don't forget its return value is allways an error code.
The cfread() and cfcopy() functions are useful to read a binary file; but if you want to use files in text format, cfgetc() and cfgets() may be more appropriate.
cfgetc() extracts a single caracter from the current position: you have to give it a char in which the data will be written, and the handle of the file to read. cfgets() can read a string of caracters that ends with a "new line" ( '\n' ) or "carriage return" ( '\r' ) caracter. The string will be copied at the specified place (and ended with a null caracter, the "new line" caracter is not copied). If it is longer than the maximum given size, it will be truncated.
One can look for certain files with the cfindfirst() and cfindnext() functions. cfindfirst() performs a first search at the specified emplacement, whereas cfindnext() searches the next entries. It is possible to use masks like '*' or '?' in this path, and to specify the attributes for the searched files (hidden, system etc). The informations on the file that has been found are stored in a FILEDATA structure. This structure is used exactly in the same way as find_t and ffblk from stdio.h.
Here is a little example:
FILEDATA data;
allowEmptyDrives();
// You should call it once at the beginning of your prog
if( cfindfirst("L:\\*.EXE", FA_NORMAL, &data) == DONE )
// search all the executables in the L drive
{
do { printf("found: %s, size %d\n", data.name, data.size); }
while( cfindnext(&data) == DONE );
}
If you don't take any precaution, you will encounter a crash if you try to find a file in an empty drive.
You can avoid this crash by using some functions from dos.h: cfindfirst() will then be able to return an "empty drive" message if this problem has appeared. This can be done with the allowEmptyDrives() function of this lib that you have to call once at the beginning of your prog. Note that this function thus need dos.h, so don't forget to comment its macro to reduce the size of your executable if you don't need it.
That's all for the explanations on this lib, I hope it was clear enough :)
Note that those functions can be used on another DOS (and windows) system. But don't forget that they were "simplified" for the AFX, and that it's thus a bad idea to use them for something else ;) I've joined a small example with the lib, don't forget to load the file "example.tst" with the prog.
Please send me a mail for any comments or suggestions!
20/12/2004
Julien PATTE
orwell01@hotmail.com