John Ivens wrote: > > Part 1.1 Type: Plain Text (text/plain) > Encoding: 7bit I'm including this in my reply to show the difficulty I have with John's email: I receive effectively an empty message with a text attachment. Since the attachment is not included in the reply I have to cut and paste it in. Yes, I know about the vagaries of email software. It would just be convenient if I could receive plain text as ... plain text. -- Bradford Castalia Castalia@Arizona.edu Senior Systems Analyst http://PIRL.LPL.Arizona.edu/~castalia Planetary Image Research Laboratory 520-621-4824 "Build an image in your mind, fit yourself into it." The Log of Cyradis, Seeress of Kell. John Ivens REALLY wrote: I think that the PDP constant indicates that its ultimately insufficient, and yet how many machines are neither LITTLE nor BIG endian? Very few machines in current use, I would suspect. So I think we can declare victory on that point. >>> Not so fast. If we have only one case of someone wanting to take advantage of the ICL using a "different" architecture, that's reason enough to support it. I always cringe at the idea that what is good enough for the majority is good enough. This is, to be crass, the Microsoft way. A better justification for the same immediate outcome is that we are building ICL lite; getting it working with what we've got. But plan for the complete solution; in the long run those minority cases are just as important as the more common ones (I happen to own a fully functional PDP-11/34A - supporting a Gould/DeAnza IP8500 image processing hardware subsystem, if you want to talk about really exotic - with which I made a decent livelihood as an independent contractor for many years; thank you very much 8^). In the long run its the minority that leads the way for the majority. So I think we can declare OK for now. This was what I did for xv. But as you are writing code try to keep in mind how the general problem might be solved and where it is likely to impact your code. For a support technology like ICL there needs to be a broader base of architecture compatibility than for most application software. If we are successful - we will be, ya - we will need to cross this bridge at some point. <<< Work is progressing (although slowly) on the pixel representation front. Dyer and I were talking about needing an interrogator object but not wanting the user to have to instantiate one. I think the solution is on page 253 of Stroustrop where he talks about a first-time switch for local static objects to make sure that they are initialized. >>> I've looked at the Stroustrup reference and agree that a "first time switch" is appropriate. I use them a lot in what I've developed. However, I also agree with Stroustrup's expansion of this topic in Section 21.5.2: It is best to put the switch in a central location rather than incur its expense in oft used functions. I'm also in the habit of doing what Stroustrup does: incorporating the first time switch into a variable this is used for some other purpose anyway. I think that the Image object instantiation ID variable could make an suitable first time switch in much the same was as Strustrup uses the counter variable in his iostream example. The initialization of the interrogator would be done in the Image object constructor (still very much pseudocode): class Image { private: static unsigned long next_ID; unsigned long ID; public: Image (); }; unsigned long Image::next_ID = 0; Image::Image () { if (! (ID = next_ID++)) { // Initialize the environment, including the Iterrogator. ... } ... } <<< // Warning -- this code is really pseudocode!! It is untried!! The driverList is not fully // implemented!! // The actual initialization trick will work, however. >>> Let's take advantage of namespaces: "ICL" sounds appropriate for now. So instead of ICL_XXX in the old C naming fashion we have "namespace ICL {" or ICL::XXX. <<< class ICL_Interrogator { static bool initialized; static bool initialize(dList driverList) { /* initialize */ initialized = true; // Do other initialization work for this class, like finding all of the mini-drivers // locations from a specified file and loading them into an array or some structure } public: // no constructor void interrogate(string &Buffer) { if (initialized == false) { initialize(driverList); } // Now do the real work of interrogating each driver // Loop through the driver array asking each one if this file is theirs // This driverList is some kind of list-like object, now PSEUDOCODE for (i=driverList.begin(); i<driverList.end(); i++) { if ( *Buffer.length() < *driverList[i].neededBufferSize() ) { // Allocate needed buffer size here // This brings up a question -- can we assume that the drivers are smart // enough to work with C++ strings? Will this need to be turned into a c_str()? >>> It's important that we make as few assumptions as possible about how a driver will be written. In addition, it's important that the necessary contraints that are imposed by the interface specification be as easy as possible to work with (as language neutral as possible). It seems reasonable to pass "strings" as null-terminated char arrays. <<< } if ( *driverList[i].belongsToMe(Buffer) ) { <<< How about: The_File_Info = new File_Info (filename /* or whatever */); foreach driver (driver_list) { // The driver object updates the buffer in The_File_Info as needed. if (driver.recognizes (The_File_Info)) The_Driver = driver, break; } if (! The_Driver) // Because it is initially null. throw Image_Open_Exception; Note that The_Driver object encapsulates whatever information is needed to interface with the driver - including the specific driver's own data block - and the interface methods on a driver. <<< // Implementation question (raised by Dyer): // Should the last chosen file type be propagated to the top of the list of // queried drivers? This would mean if the user wanted to open 100 images in a // row, and get a pixel out of each one, and each file was the same type // (like VICAR), then each file after the first one would be read in as quickly as // possible because the VICAR driver would be the first one checked. >>> Good question. I would generalize this into the issue of driver list management. It seems that there will be numerous operations that both the ICL and the user may want to do on the list including reordering the list based on an application provided configuration file, keeping track of the last used driver and using this first instead of the default order based on a mode setting, adding and dropping entries to the list in addition to the usual querying, providing the list in a form suitable for inclusion in a text configuration file, etc. <<< return (&driverList[i].driver()); } // No driver matched -- return unknown return (NULL); <<< Shouldn't an exception be thrown instead of NULL returned (here we go again)? <<< } } So the user does something like: ICL_Image iclm = new ICL_Image("this_file"); The constructor for ICL_Image does something like this: ICL_Image::ICL_Image(string fileName) { // blah blah, make buffer of default size, blah blah string Buffer[256]; // Note that we don't have to instantiate the ICL_Interrogator class, it initializes itself // This means that the driver file only needs to be read once. driver theDriver = ICL_Interrogator.interrogate(Buffer); // We don't know what size the Buffer will be when it returns... header theHeader = theDriver.readHeader(Buffer); } This will then allow interrogation of the header and further reading of >>> I don't think the ICL core should know anything about "headers". This is the driver's business. The ICL knows about image attributes and pixel data but always uses the driver to obtain them. In writing a driver I would probably read the entire header into a data block in a form optimized for later use (e.g. as a PPVL hierarchy) and attach this (as a pointer to where the data is in memory) to the driver data block carried around by the Image object. It will be there for me when the ICL passes the driver data block (again as a reference) to me over the interface. For the initial interrogation, however, I (as a small module related to, but separate from the main driver module) will do as little as possible to determine if The_File_Info refers to a file that I know about. Perhaps, if I do recognize the file, I will invoke the main driver module and initialize it (which could then read the entire header), returning a fully initialized driver to the ICL core. This would obviate the need for a first time switch in the main driver module. <<< the file contents. More to come... and this will probably change into a better object model when you guys review this... :) -- When I use a word it means just what | John Ivens I choose it to mean - neither more | Principal Programmer nor less. | Cassini VIMS -- Humpty Dumpty | (520) 621-7301