2004.08.26 16:03 "Re: [Tiff] Not-a-bug report, TIFFFdOpen (tif_win32) - TIFFClientOpen", by Ross A. Finlayson
How about this:
- We change tiff2pfd and fax2tif to use clientdata, making tiff_fd unused in the tools like in the library, the way you proposed.
- We add a TIFFFilenoSet function, that sets the tif_fd member. That way, we can achieve an opaque TIFF* even for code that activelly uses this tif_fd, on the one hand, and we'd have added a 'usefull' extra clientdata member accessable for the code that already treats TIFF* as opaque on the other hand.
- We change the platform dependent tif_* units to use TiffFilenoSet, instead of directly accessing the member, and are then able to enforce the rule that TIFF* should be opaque in those units.
How does this sound to you?
We often have the luxury of source compatibility, that means if the TIFF structure was changed and someone compiled against the new yet linked against an old library then there would be undefined behavior.
I think the function should be TIFFSetFileNo instead of TIFFFileNoSet, which sounds more like checking if it is non-zero.
That sounds OK for removing most references to tif_fd, but in something like fax2tiff or tiff2pdf there is still explicit setting of the tif_clientdata. So if you want no access to the member in those functions then you would need getter/setter (accessor/mutator) functions for tif_clientdata as well as tif_fd.
The tif_fd member is vestigial and can be removed, all it ever does is be set to the file descriptor and then immediately the clientdata is set to the file descriptor and the read/write/seek procedures work on the clientdata. That seems to be one issue where another is the tif_clientdata itself and having an opaque pointer so that user software need not include anything but tiff.h and tiffio.h, for example tiffiop.h, p for private, where the TIFF struct is defined, although it is as well declared forwardly in tiff.h as a forward definition.
So if you add the Get/SetClientData, or FileNo, function into the tiffio.h, then the user would not need to include tiffiop.h to compile programs like fax2tiff, or tiff2pdf.
There are functions to do with the client info which is not the client data.
So, if you figure that anyone who compiles the new software wil link against the same version of the library, then tif_fd is is easily deleted and all references to it are changed to tif_clientdata, and vice versa. As a separate issue, you can add thandle_t TIFFGetClientData and TIFFSetClientData(thandle_t fd) to get and perhaps set both of tif_fd and tif_clientdata that remain in the struct definition.
Then TIFF* would be opaque in the tools and platform I/O units, and those functions would still be available.
Changing the structure but not the shared library against which functions on the struct are linked and called is one of the problems causing what at one time was called "DLL Hell", where the very version of the DLL had to match the pointer definition against which its functions were compiled. That's one reason to add new fields to the struct at the end of the struct definition, with no side effects among the struct members, with an opaque struct, so old and new libraries can use the struct.
That's not very much the issue here if both tif_fd and tif_clientdata remain in the TIFF*, with functions to set them set both, with implementation knowledge that thandle_t is an integer, and then the user as before is responsible for calling the correct functions upon them, but they will be able to access them from tiffio.h.
So the setter function should set both of them.
Anyways I think the functions would be
void TIFFSetFileNo(TIFF*, thandle_t)
void TIFFSetClientData(TIFF*, thandle_t)
For convenience, the setter function could return the previously set file decriptor instead of void.