[comp.sys.mac.programmer] Is there a defacto standard for 'drop ins'?

time (Tim Endres) (03/22/91)

In article <1991Mar21.223638.4346@ssd.kodak.com>, ph@ssd.kodak.com (Pete Hoch) writes:
> So I was wondering, do they all do it the same way?  Should
> Apple step in and provide a filter manager?  Is this hard to
> do today without Apples help?  Also, is this a good idea?

Most of these mechanisms use a very similar technique.

However, all differ in content and calling conventions, and it is
very doubtful that a universal solution would be easily decided upon.
However, I am certain some could be standardized. For instance, there
could be a common interface for operations that work on text selections.
Of course, even then, some cases will still not fit...

-------------------------------------------------------------
Tim Endres                |  time@ice.com
ICE Engineering           |  uupsi!ice.com!time
8840 Main Street          |  Voice            FAX
Whitmore Lake MI. 48189   |  (313) 449 8288   (313) 449 9208

ph@ssd.kodak.com (Pete Hoch) (03/22/91)

Hi all,

I have noticed lately that more and more applications are
supporting 'drop in' code resources.  Perhaps the most
famous example of this is PhotoShop.  However StuffIt now
supports drop in filters and even Apple's own Communications
tool box will run seperate code segments.

So I was wondering, do they all do it the same way?  Should
Apple step in and provide a filter manager?  Is this hard to
do today without Apples help?  Also, is this a good idea?

It seems to me that it would be hard tocome up with a general
toolbox interface that would handle any filtering need that
application programmers could come up with.  However there
are some basic concepts of piping and filtering that have
stood the test of time in UNIX.  Would it be usefull to say
have a filtered read command so that when an application
reads a disk file that byte stream passes through a filter
on its way in?

Perhaps I have not phrased my questions well but if you have
some ideas on how to go about doing this I would be very interested.

Pete Hoch



-- 
Pete Hoch                                  | ..somewhere..!kodak!ph   ..or..
Color Systems ISPD. 3/65/RL		   | ph@ssd.kodak.com         ..or..
Eastman Kodak Co. 	   		   | ph@kodak.com
Rochester, NY 14650-1805                   | 716-722-????

hawley@adobe.COM (Steve Hawley) (03/23/91)

In article <1CE00001.aolmdnz@tbomb.ice.com> time@ice.com writes:
>
>In article <1991Mar21.223638.4346@ssd.kodak.com>, ph@ssd.kodak.com (Pete Hoch) writes:
>> So I was wondering, do they all do it the same way?  Should
>> Apple step in and provide a filter manager?  Is this hard to
>> do today without Apples help?  Also, is this a good idea?
>
>Most of these mechanisms use a very similar technique.
>
>However, all differ in content and calling conventions, and it is
>very doubtful that a universal solution would be easily decided upon.
>However, I am certain some could be standardized. For instance, there
>could be a common interface for operations that work on text selections.
>Of course, even then, some cases will still not fit...

Since Pete was interested in a general way of doing filters, why not have
the following (off the top of my head) for byte oriented streams:

typedef struct {
/* stream operations.  These would probably follow Pascal calling conventions */
	boolean (*EndOfStreamFunc)();
	char (*GetCharFunc)();
	OSErr (*PutCharFunc)();
	OSErr (*UngetCharFunc)();
	/* maybe Seek, and Length too */
} StreamOps, *StreamOpsPtr;

/* prototype function to do filtering */
pascal void main(SOps)
StreamOpsPtr SOps;
{
	/* your code to do filtering */
}

The idea is that the parent program passes in pointer to functions to do all
operations one would need for a stream.  The main could then use the ops on
the stream to transform the data as needed:

pascal void main(SOps)
register StreamOpsPtr SOps;
{
	/* convert an uppercase bytes stream to lowercase */
	register char *c;
	while (! (SOps->EndOfStreamFunc)()) {
		c = (SOps->GetCharFunc)();
		if (isupper(c)) c = tolower(c);
		/* whatever the syntax is for CallPascal -- I forget */
		CallPascal1(SOps->PutCharFunc, c);
	}
}

Of course, this will not be particularly speedy because of the overhead added
by the function calling, but you wanted generality, right?

Steve Hawley
hawley@adobe.com
-- 
"Did you know that a cow was *MURDERED* to make that jacket?"
"Yes.    I didn't think there were any witnesses, so I guess I'll have to kill
 you too." -Jake Johansen

d88-jwa@byse.nada.kth.se (Jon W{tte) (03/25/91)

In article <13094@adobe.UUCP> hawley@adobe.COM (Steve Hawley) writes:

   typedef struct {
   /* stream operations.  These would probably follow Pascal calling
	conventions */
	   boolean (*EndOfStreamFunc)();
	   char (*GetCharFunc)();
	   OSErr (*PutCharFunc)();
	   OSErr (*UngetCharFunc)();
	   /* maybe Seek, and Length too */
   } StreamOps, *StreamOpsPtr;

You would rather want to get blocks at a time - like,

typedef struct {
	long		amountToRead ;
	long		flags ; /* bit 0 == SetPosition supported &c */
	pascal OSErr	( * ReadBlock ) ( char * , long ) ;
	pascal OSErr	( * PeekBlock ) ( char * , long ) ;
	pascal OSErr	( * WriteBlock ) ( char * , long ) ;
	pascal OSErr	( * SetPosition ) ( char * , long ) ;
	pascal OSErr	( * TellUser ) ( char * ) ;
} filterParam ;

pascal OSErr
MyFilterFunc ( filterParam * p , char * userData )
{
}

Or should it be handle-based ? Maybe bit 1 == Handles instead of
pointers ? Who should be responsible for allocating memory ? Should
operations in site be allowed ? (more flags :-)

userData could be filter-dependent, like "awk" command lines, or
it could be app-dependent.

More ideas ! Maybe the Net is strong enough to actually support
a de-facto standard. But we'd have to talk a few major players
into using this standard.

Happy hacking,

						h+@nada.kth.se
						Jon W{tte
--
"The IM-IV file manager chapter documents zillions of calls, all of which
seem to do almost the same thing and none of which seem to do what I want
them to do."  --  Juri Munkki in comp.sys.mac.programmer

peirce@outpost.UUCP (Michael Peirce) (03/25/91)

I think drop-ins can be very useful at times, but I hope that with
System 7, people will start thinking about using AppleEvents to do
some of this type of thing too.

It would be nice to be able to ask a spell checker app to check something
for us for example.  Or a data compression app to compress something, etc.

This demands acceptance of some standard AppleEvents to make this work
of course.

-- michael

--  Michael Peirce         --   outpost!peirce@claris.com
--  Peirce Software        --   Suite 301, 719 Hibiscus Place
--  Macintosh Programming  --   San Jose, California 95117
--           & Consulting  --   (408) 244-6554, AppleLink: PEIRCE

hawley@adobe.COM (Steve Hawley) (03/26/91)

In article <D88-JWA.91Mar24213927@byse.nada.kth.se> d88-jwa@byse.nada.kth.se (Jon W{tte) writes:
>You would rather want to get blocks at a time - like,
>
>typedef struct {
>	long		amountToRead ;
>	long		flags ; /* bit 0 == SetPosition supported &c */
>	pascal OSErr	( * ReadBlock ) ( char * , long ) ;
>	pascal OSErr	( * PeekBlock ) ( char * , long ) ;
>	pascal OSErr	( * WriteBlock ) ( char * , long ) ;
>	pascal OSErr	( * SetPosition ) ( char * , long ) ;
>	pascal OSErr	( * TellUser ) ( char * ) ;
>} filterParam ;

Actually, I wouldn't want to get blocks at a time.  The reason why I suggested
a byte stream is that the parent program can decide what buffering scheme is
most appropriate for the the drop-in module, and bytes streams will be free
from typical problems associated with block reads: matching block size with
ths OS for efficiency, byte ordering, word/long word alignment, what happens
when I can't allocate a block size that I expected (do I put an alert? *CAN*
I put up an alert?  Am I allowed to move memory?) etc.


It all depends on what you want, really.  A stream oriented program is geared
especially well for text and files and will work with a minimum of hassle with
for many other applications as well.  The outline of a stream based filter
is straight forward and uncomplicated (for the most part -- there are always
degenerate cases).  It is simply easier to write a correct stream-based filter
than it is to write a correct block-based filter, and you are forcing everyone
who writes a drop in module to do their own buffer handling.  If you have a
program with a couple dozen drop-in modules, wouldn't you rather have the block
buffering in one place than in 20?


The down side (as I mentioned before) is that you pay for a function call for
each byte you read.  Obviously, for something like filtering of, say, 24 bit
graphics data, a stream-oriented method is going to be extremely painful.  In
fact, so will a block-oriented method unless the only block that gets passed
is a pointer or handle to a data structure describing the data (like a PixMap).


So, back to the original question of "why is there no standard way for handling
drop-in modules?"  Do you have your answer now?  Because no two people will
ever agree on what is a "good" standard and the approach you take must be
geared for the type of data you intend to be fiddling with.


I'm glad I don't work on a standards committee...

Steve Hawley
hawley@adobe.com
-- 
"Did you know that a cow was *MURDERED* to make that jacket?"
"Yes.    I didn't think there were any witnesses, so I guess I'll have to kill
 you too." -Jake Johansen

d88-jwa@byse.nada.kth.se (Jon W{tte) (03/26/91)

In article <13180@adobe.UUCP> hawley@adobe.COM (Steve Hawley) writes:

   Actually, I wouldn't want to get blocks at a time.  The reason why I
   suggested a byte stream is that the parent program can decide what
   buffering scheme is most appropriate for the the drop-in module, and

What keeps you from reading blocksa of 1 byte ? And what keeps the
host application from passing pointers into its own buffers ? It tells
the filter how much there is to read, and the filter tells the host
how much it wants...

   than it is to write a correct block-based filter, and you are forcing
   everyone who writes a drop in module to do their own buffer handling.

Do I ?

   drop-in modules?"  Do you have your answer now?  Because no two people will
   ever agree on what is a "good" standard and the approach you take must be
   geared for the type of data you intend to be fiddling with.

Hmmm... well, maybe I'll sit down and design a _real_ complex interface
that lets you pass whatever you choose, and automatically handles
interface kinks, as well as lowers your taxes and configures sendmail
for you.

:-)

							h+@nada.kth.se
							Jon W{tte
--
"The IM-IV file manager chapter documents zillions of calls, all of which
seem to do almost the same thing and none of which seem to do what I want
them to do."  --  Juri Munkki in comp.sys.mac.programmer

time@ice.com (Tim Endres) (03/26/91)

In article <D88-JWA.91Mar26101759@byse.nada.kth.se>, d88-jwa@byse.nada.kth.se (Jon W{tte) writes:
> Hmmm... well, maybe I'll sit down and design a _real_ complex interface
> that lets you pass whatever you choose, and automatically handles
> interface kinks, as well as lowers your taxes and configures sendmail
> for you. :-)

And if you can get it to handle my lawyers, you'd really have something!!!

:-)^2

tim.

-------------------------------------------------------------
Tim Endres                |  time@ice.com
ICE Engineering           |  uupsi!ice.com!time
8840 Main Street          |  Voice            FAX
Whitmore Lake MI. 48189   |  (313) 449 8288   (313) 449 9208

ph@ssd.kodak.com (Pete Hoch) (03/27/91)

>><1991Mar21.223638.4346@ssd.kodak.com>, ph@ssd.kodak.com (Pete Hoch) writes:
>>> So I was wondering, do they all do it the same way?  Should
>>> Apple step in and provide a filter manager?  Is this hard to
>>> do today without Apples help?  Also, is this a good idea?

>In article <1CE00001.aolmdnz@tbomb.ice.com> time@ice.com writes:
>>Most of these mechanisms use a very similar technique.
>>However, all differ in content and calling conventions, and it is

In article <13094@adobe.UUCP> hawley@adobe.UUCP (Steve Hawley) writes:
>Since Pete was interested in a general way of doing filters, why not have
>the following (off the top of my head) for byte oriented streams:

   prototypes deleted

>The idea is that the parent program passes in pointer to functions to do all
>operations one would need for a stream.  The main could then use the ops on
>the stream to transform the data as needed:

>Of course, this will not be particularly speedy because of the overhead added
>by the function calling, but you wanted generality, right?

However the overhead could be such a problem that this would not be
practical.  What I was thinking was something more allong the lines
of a call back routine that the programmer supplies to the system.

For example:
    pascal OSErr myFilter( void    *source,     // The data comes from
                           long    sSize,       // size of the data in bytes
                           long    sNext,       // offset to the next sample
                           void    *dest,       // The data goes to
                           long    dSize,       // size of the data in bytes
                           long    dNext)       // offset to the next sample

Then you need a way to select and install filters.  Perhaps the Comm ToolBox
is a good example of this and can be expanded and generalized.

Pete

-- 
Pete Hoch                                  | ..somewhere..!kodak!ph   ..or..
Color Systems ISPD. 3/65/RL		   | ph@ssd.kodak.com         ..or..
Eastman Kodak Co. 	   		   | ph@kodak.com
Rochester, NY 14650-1805                   | 716-722-????

ph@ssd.kodak.com (Pete Hoch) (03/27/91)

In article <0B010004.ma805a@outpost.UUCP> peirce@outpost.UUCP writes:
>I think drop-ins can be very useful at times, but I hope that with
>System 7, people will start thinking about using AppleEvents to do
>some of this type of thing too.
>
>It would be nice to be able to ask a spell checker app to check something
>for us for example.  Or a data compression app to compress something, etc.
>
>This demands acceptance of some standard AppleEvents to make this work
>of course.
>
>-- michael

This is all well and good for System 7.0 but what about all of the
people that still use 6.X?  Also there are some things that cannot
take the performance hit inherent in AppleEvents.  If we can get
a good general flexable design for drop in code filters it would
be a trivial matter to write a faceless app in 7.0 that accepted
AppleEvents and then called the filter manager.  So I still think
the basic design of a general filter manager is worth talking about.

Pete


-- 
Pete Hoch                                  | ..somewhere..!kodak!ph   ..or..
Color Systems ISPD. 3/65/RL		   | ph@ssd.kodak.com         ..or..
Eastman Kodak Co. 	   		   | ph@kodak.com
Rochester, NY 14650-1805                   | 716-722-????

hawley@adobe.COM (Steve Hawley) (03/27/91)

In article <D88-JWA.91Mar26101759@byse.nada.kth.se> d88-jwa@byse.nada.kth.se (Jon W{tte) writes:
>What keeps you from reading blocksa of 1 byte ? And what keeps the
>host application from passing pointers into its own buffers ? It tells
>the filter how much there is to read, and the filter tells the host
>how much it wants...

Nothing *keeps* you from reading one byte blocks.  You're right.  But tell me,
do _you_ define getchar like this?

int mygetchar()
{
	char c;
	if (read(0, &c, 1)) return(c);
	else return(EOF);
}

Just for kicks I wrote a program to consume standard input (under UNIX) and
found that using standard getchar takes .2 seconds of user time and .2 seconds
of system time to read the man page for the c shell.  The same program with
mygetchar used instead requires 3.4 seconds of user time and 43.4 seconds of
system time.

Now, as a final trick, I modified mygetchar() to use a 8192 bytes buffer
instead of a 1 bytes buffer to simulate a drop in module with a fairly
generous buffer size.  It took .1 seconds of user time and .1 seconds of system
time.  Not significantly different over a 75K file.

>   than it is to write a correct block-based filter, and you are forcing
>   everyone who writes a drop in module to do their own buffer handling.
>
>Do I ?

No, you're right.  You don't _have_ to write buffer handling routines.  See
above for what happens when you don't have them, and if the only way to get
buffered IO is by putting it in the drop in module and stream oriented I/O
is the most appropriate means of getting bytes across then your application
will be much bigger than it has to be because for every drop in module, there
will be stream I/O code with buffer management.

Now before we start getting into another series of "great taste/less filling"
arguments, please keep in mind that I am not rabidly against block style I/O,
nor am I rabidly for stream-style buffered I/O.  Let's be computer scientists
for a minute, OK?  Can you implement stream-style buffered I/O using block
style I/O routines?  Yes?  Good.  Can you implement block-style unbuffered I/O
routines with stream routines?  Let's not see the same hands...  Right, you
can.  Gosh!  They're equivalent!  So why use one over the other?  Only your
application will dictate which is more appropriate.  If I write a terminal
emulator and decide that I want to allow drop in modules for transfer protocol
or emulation, I'm probably going to want to use stream IO.  If I write something
like PhotoShop, I'd probably want block IO (in fact, I'd probably rather have
the pointer to a data structure).

The important point (do I really have to type this for the third time?) which
is the answer to the original question of "why is there no standard means of
doing drop-in modules" is that there is no standard task that needs to be done
by a drop-in module.  The needs are different, so therefore are the means of
satisfying that need.

My original article was meant to pose a general, not universal, method for
handling communication between a parent application and drop-in modules.  I
chose a stream model for a few reasons:
1) It's simple to interface to
2) It's reasonably efficient for a wide range of tasks
3) The directional nature of it allows for easy connection (similar to pipes)
   bewteen modules.
4) Provides a "feel" similar to UNIX stream IO.

I realy didn't mean for this to get into so much "block IO! Nyah! stream IO!
Nyah!" traffic.  Really.

Steve Hawley
hawley@adobe.com
-- 
"Did you know that a cow was *MURDERED* to make that jacket?"
"Yes.    I didn't think there were any witnesses, so I guess I'll have to kill
 you too." -Jake Johansen

urlichs@smurf.sub.org (Matthias Urlichs) (03/28/91)

In comp.sys.mac.programmer, article <13180@adobe.UUCP>,
  hawley@adobe.UUCP (Steve Hawley) writes:
< 
<The down side (as I mentioned before) is that you pay for a function call for
<each byte you read.  Obviously, for something like filtering of, say, 24 bit
<graphics data, a stream-oriented method is going to be extremely painful.  In
<fact, so will a block-oriented method unless the only block that gets passed
<is a pointer or handle to a data structure describing the data (like a PixMap).

You could conceivably get the best of both worlds by also passing a parameter
on how many bytes to read. The drop-in module should of course be able to
handle partial reads.

If you want to get fancy, pass another parameter to flag that the application
should stop after the first CR, thus implementing line-at-a-time reads.

It might also be a good idea to lock the buffer and pass its address back to
the filter instead of copying the data into the filter's buffer; most filters
can't read into their final data structure anyway -- a filter's job is to
convert data, right?

How do existing filter interfaces (Claris, Stuffit) handle these problems?

-- 
Matthias Urlichs -- urlichs@smurf.sub.org -- urlichs@smurf.ira.uka.de     /(o\
Humboldtstrasse 7 - 7500 Karlsruhe 1 - FRG -- +49-721-621127(0700-2330)   \o)/

ph@ssd.kodak.com (Pete Hoch) (03/28/91)

In article <13225@adobe.UUCP> hawley@adobe.UUCP (Steve Hawley) writes:

> If I write a terminal emulator and decide that I want to allow drop
> in modules for transfer protocol or emulation, I'm probably going to
> want to use stream IO.  If I write something like PhotoShop, I'd
> probably want block IO (in fact, I'd probably rather have
> the pointer to a data structure).

How about if we go one further and instead of a pointer to a data
structure we define a whole object.  The data object would need
methods for data access to override, but the actual data storage
etc, would be left up to the subclass.  Apple has been claiming
for almost two years now that objects are the way to go.  Prehaps
this is the time to design a filter manager that coordinates the
instilation of filter objects.  (Are you listening CTB developers?)

>The important point (do I really have to type this for the third time?) which
>is the answer to the original question of "why is there no standard means of
>doing drop-in modules" is that there is no standard task that needs to be done
>by a drop-in module.  The needs are different, so therefore are the means of
>satisfying that need.

Perhaps my original question was based at too low a level.  Let me refraze.

I have noticed the use of 'drop in' code in more and more application.
Examples of this are Photoshop, Stuffit, and the comm toolbox.  All of
these have their own way of selecting the 'drop in' code from the
users point of view.  And each had to impliment a method for loading
and exicuting the `drop ins`.  So what I was really thinking, (if not
specificly asking) was, can there and *should there* be a high level
filter manager that regardless of functionality will provide the user
with a consistent way of dealing with 'drop ins'?

>I realy didn't mean for this to get into so much "block IO! Nyah! stream IO!
>Nyah!" traffic.  Really.

Me either.

Pete

-- 
Pete Hoch                         | ..somewhere..!kodak!ssd!bashow!ph   ..or..
Color Systems ISPD. 3/65/RL       | ph@ekcolorlink.ssd.kodak.com        ..or..
Eastman Kodak Co. 	          | ph@bashow.ssd.kodak.com
Rochester, NY 14650-1805          | 716-722-3285

time@ice.com (Tim Endres) (03/30/91)

In article <1991Mar27.204705.5725@ssd.kodak.com> you write:
> and exicuting the `drop ins`.  So what I was really thinking, (if not
> specificly asking) was, can there and *should there* be a high level
> filter manager that regardless of functionality will provide the user
> with a consistent way of dealing with 'drop ins'?

In uAccess, the user can add drop-ins two ways. One is to drop resources
into a specified file. The other is to move files into a specified
folder. The former is hard, the latter easy.

What would be nice is if Apple provided a common mechanism, similar
to the Control Panel, that would provide a common interface for all
applications for adding, removing, and configuring drop-ins.

As for a "universal" calling convention, seems like a waste of effort,
since not every case can be fully covered. HOwever, it does seem that
a large number of "obvious" cases could be generalized. For instance,
uAccess has drop-ins that work on text selections in a text window.
This is the type of operation that could be generalized.

tim.

-------------------------------------------------------------
Tim Endres                |  time@ice.com
ICE Engineering           |  uupsi!ice.com!time
8840 Main Street          |  Voice            FAX
Whitmore Lake MI. 48189   |  (313) 449 8288   (313) 449 9208