On Tue, 2005-10-11 at 17:45 -0400, Paul Alfille wrote:
> Ok, Geo. I'm convinced.
> 
> Look in the CVS for owcapi. (libowcapi.so.0.0.0)
> 
> Very simple library:
> int OW_init( const char * device ) ;

What's device? Why is the programmer concerned? Isn't it a target-system
specified thing?

Perhaps the environment variable OWDEVICE would be more appropriate.

If you're really intent on letting the user set it here, perhaps making
device==NULL should use getenv("OWDEVICE") - and if that's not
specified, perhaps some automatic hunting?

If hunting is really inappropriate, have OW_init() simply fail.


> int OW_get( const char * path, char * buffer, int buffer_length ) ;

Don't let the programmer specify a buffer length for gets. It's prone to
programming errors. The extra malloc() isn't going to cause any real
problems, but if you're worried, a:

int OW_get_buffer(const char *path,char*buffer,int buffer_length);

in addition to:

int OW_get(const char *path,char**buffer);

> int OW_put( const char * path, const char * buffer, int buffer_length ) ;
> void OW_finish( void ) ;

Most of my programs are small. I write them small so I can avoid bugs
(security or otherwise), so I have wrappers that look like this:

void*memalloc(unsigned int s) {
        void*q;
        if (!(q = malloc(s))) { perror("malloc");exit(255); }
        return q;
}

This does the right thing 99% of the time, so I'd recommend some
additional api:

void OW_errhandle(int(*f)(int e));

that sets up global error handling for OW:
        f == function
                this calls the function when an error occurs-
                useful for emulating (or using) real exceptions
                in gcc, OBJC, or C++. if it returns, this is
                the "real" return code used.
Some supplied functions:

int _OW_err_ansi(int e) { return e; }
        use error reporting like ANSI/POSIX C does. This means
        the user is expected to check return codes.

int _OW_err_throw(int e) {
        if (e > CRITICAL) { perror("whatever"); exit(255); }
        return e;
}
        this should be the default.

        automatically exits on critical errors. Note this isn't
        the same as nonrecoverable errors- those should ALWAYS
        kill the current process (preferably with abort())

        critical errors are the kind that it's probably the USER
        that wants to recover from them and not the programmer.
        good examples are:
                * out of memory
                * invalid or nonfunctioning device spec (OW_init)
                * put format specification violation

I also recommend:

void OW_blocking(int f);
        if f is true, OW blocks. this is the default.
        if f is false, OW will return OW_BUSY instead of blocking. It will also
setjmp() a special buffer. Until OW_completion()
        is called, all other OW_* operations generate a critical error,
        OW_NOSTACK

int OW_completion(void);
        when called, the stack will be guaranteed to be equal-to
        or deeper in depth than when the last blocking call that
        returned OW_BUSY. It then performs a longjmp() to the
        last operation to complete it.

        if it returns (and it returns if still busy, or if no
        operation is pending), it returns a file descriptor that
        can be select()d on to determine whether or not an operation
        will block.


APIs do NOT need to be complicated in order to be useful. The trick is
to make sure the user can step up the API as they need it.

Btw, specify in documentation:
        OW_* calls aren't reetrant or thread-safe. Serialize yourself.


> Seems to work.
> 
> Paul
> 
> On Tuesday 11 October 2005 04:44 pm, Geo Carncross wrote:
> > On Fri, 2005-10-07 at 14:06 -0400, Alfille, Paul H.,M.D. wrote:
> > > Sven,
> > >
> > > It would be easy to do. The real problem is string handling. We'd have to
> > > specify buffers and lengths.
> >
> > Why?
> >
> > int get_value(const char *path, char **ret, unsigned int *retlen);
> >
> > Would be adequate and not require a buffer, and if everything is
> > ASCIIZ-safe, using:
> >
> > int get_value(const char *path, char **ret);
> >
> > would be fine too.
> >
> > > So for a directory listing, you would get either a long string to be
> > > parsed, or an array of strings.
> >
> > Why not a pointer to an array and a list?
> >
> > Or an iterator? [think about how opendir() works]
> >
> > > Also, the return types are multiple, integer, string or floating. It
> > > would probably be better to get the raw data type rather than have to
> > > reparse the ascii interpretation.
> >
> > Why would it? That just makes it complicated.
> >
> > Since it's already in the string form, parsing it again for me doesn't
> > help. After all, I might be able to get by with something that becomes
> > equivelent to:
> >
> > unsigned int q = *(unsigned int*)ret;
> > if (q&255) { /* must not be a three-digit number */ }
> >
> > The user already knows how to use atoi(), and if they want to use it,
> > this really won't cost them a lot in cpu-time. Nothing compared to
> > context-switches and the fact that 1wire is already really slow :)
> >
> > > Choices in C:
> >
> > I think the real-deal is avoiding the context switches and
> > code-complexity.
> 
> 
> -------------------------------------------------------
> This SF.Net email is sponsored by:
> Power Architecture Resource Center: Free content, downloads, discussions,
> and more. http://solutions.newsforge.com/ibmarch.tmpl
> _______________________________________________
> Owfs-developers mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/owfs-developers
-- 
Internet Connection High Quality Web Hosting
http://www.internetconnection.net/



-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
Owfs-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/owfs-developers

Reply via email to