libdatablks API documentation ============================= For version 0.99.1, written by Nick Rusnov (C) Copyright 1999 by Nick Rusnov, relased under the same terms as the rest of this package. Introduction ------------ Libdatablks is a small library that implements a simple data type modeled after LambaMOO's variable types. It is written in what should be fairly portable flat C. It was written for two separate, complimentary projects; the first, a LambdaMOO-like server called IO; the second a CORBA/COM-like (well, in concept at least) ORB/ object protocol. This library could be useful for all kinds of stuff, like language interpreters. A data-block (Datablk *) is a simple structure that contains the type, a pointer to a tail (for list structures), a pointer to the actual data, and some flags. You as a programmer writing applications and stuff shouldn't worry too much about the actual contents of the structure unless you plan on fixing or extending the library; I designed the API to be reasonably "OOP"ly, with functions providing all the interface to the structures for you. Besides, the structure could up and change on you, and then where would you be? [ObEvilLaugh] Note that in examples herein I leave off the dblk_ prefix for functions, which should be present if you want you programs to work. The Types and their Purposes ---------------------------- A Datablk, from C's point of view, is a "type-less type", it can contain any type, so a function that is passed a Datablk could accept almost anything form strings to lists through it. However, the Datablk still needs to know what it is carrying so it knows how to dispatch the data. The following table shows the types a Datablk knows about: Type C symbol Description ------------------------------------------------------------------ (general types) Numeric DBLK_T_NUM Any number, C types int, float, long, etc String DBLK_T_STR A char * string List DBLK_T_LIST A linked-list or lisp-like list. (moo-like specific types) Object Ref. DBLK_T_OBJR An "object reference", more below. Object Inst. DBLK_T_OBJI An "object instance" (unimpl) Error DBLK_T_ERR Error code and message The MOO-like types are somewhat useless in many circumstances, but who knows, maybe they'll come in handy. Generic Functions: Type-less Workhorses --------------------------------------- DBLK_INIT(Datablk *, type) This is a sugar macro for creating an empty but allocated Datablk, it is mostly used internally, and is most useful in extensions. dblk_destroy(Datablk *) This destroys a Datablk, including freeing the data fork, and things linked to its tail (recursively). dblk_nullify(Datablk *) This frees the data part of a Datablk, effectively "zeroing" it out. int dblk_typeof(const Datablk *) This is a sugar function that returns Datablk->type right now. Use this instead of accessing the structure directly. Datablk *dblk_mkclone(const Datablk *) This allocates and returns a new Datablk that is a copy of the first argument. This operates non-recursively (it doesn't follow the tail). dblk_mkcopy(const Datablk *src,Datablk *dest) This copies src into a previously existing Datablk, dest, freeing dest's value as appropriate. Datablk *dblk_mkrclone(const Datablk *) This does the same thing as mkclone, except it follows the tail and copies recursively; this should be used in most general-use circumstances, the regular mkclone is mostly for special cases and internal use. dblk_mkrcopy(const Datablk *src,Datablk *dest) Does the same as mkcopy, with the same differences as mkrclone. T_NUM Functions --------------- The numeric functions are somewhat lacking at this point. Datablk *dblk_mknum(const double) Allocate a new Datablk with the value. double dblk_getnum(const Datablk *) Return the numeric value from a Datablk. dblk_setnum(const double, Datablk *) Set the Datablk's value to the number, gracefully destroy the old value. T_STR Functions --------------- These functions are also somewhat lacking. Datablk *dblk_mkstr(const char *) Allocate a new Datablk with the value. char *dblk_getstr(const Datablk *ablk) Return a newly allocated string that is a copy of the one contained in the Datablk. const char *dblk_getcstr(const Datablk *) Return the "live", though const'd string contained in the Datablk. dblk_setstr(const char *, Datablk *) Set the Datablk to the (copied) string. Lists and T_LIST Functions -------------------------- Lists are implemented as dynamic linked lists. Through the T_LIST functions, they act a lot like Lisp and MOO lists. There are really two types of lists in a sense. The first is an "official" list, one that looks like: Datablk |\type->T_LIST \data->Datablk (element 1) | (tail) Datablk (element 2) That is, a master Datablk which is a placeholder of type T_LIST, whose data fork is a linked list of other Datablks of undetermined type, connected by their tails. The second is an "unofficial" list, which is the same, but without the placeholder Datablk, in other words a flat linked list. Note that any function in the T_LST section that takes a Datablk to be added to a list will "walk" the Datablk if its an unofficial list.. that is, it will go to the end of the linked list, effectively merging it into the new list. For example, given the unofficial lists: a=1,2,3 b=4,5,6 z=mkpacklist(a,b) would yield the official list z={1,2,3,4,5,6}. Also note that functions intended to operate on T_LISTs will only operate on official lists. Datablk *dblk_mkpacklist(const Datablk *,...) This function takes as many Datablk *s as you want to pass to it and copies their values, constructing a list out of them and returning it. int dblk_llength(const Datablk *) This returns the length of a list. Datablk *dblk_lindex(const int index, Datablk *list) This returns a live pointer to a Datablk at a certain index in a list. This pointer can be used to modify or read the value at that index in place. It would be a very bad idea to deallocate this pointer in any way, or damage its tail. Datablk *dblk_lindexv(const int index, Datablk *list) This merely lifts a copy of a Datablk at a certain index of a list. This copy is yours and changing it doesn't touch the list it came from. dblk_linsert(const int index, Datablk *list, const Datablk *element) This inserts a new Datablk which is a copy of the element Datablk at index. Datablk *dblk_lremove(const int index, Datablk *list); This removes the Datablks at index from list and returns its pointer. To delete an element from a Datablk list, you'd do something like destroy(lremove(n,list)). int dblk_lpush(Datablk *list, const Datablk *elm); Datablk *dblk_lpop(Datablk *list); int dblk_lunshift(Datablk *list, const Datablk *elm); Datablk *dblk_lshift(Datablk *list); These all treat lists like stacks or queues. They are similar to the functions in Perl for dealing with arrays. They are merely sugar functions for linsert and lremove. Errors and T_ERR Functions -------------------------- Errors are a simple compound type intended to pass "error codes" and accompanying messages. The C type for errors is DBLK_ERR. Datablk *dblk_mkerr(const DBLK_Err *) This creates a new Datablk with a copy of the error passed as its value. Datablk *dblk_mkgenerr(const int code, const char *message) This creates a new Datablk with a newly-created Error with the code and message specified. dblk_geterr(DBLK_Err *, const Datablk *) This copies the error value contained in the Datablk into the already existing error object. dblk_seterr(const DBLK_Err *, Datablk *) This sets the value of the Datablk to a copy of the error. dblk_setgenerr(const int code, const char *message, Datablk *) This sets the value of the Datablk to a newly created error with the code and message specified. DBLK_INIT_ERR(DBLK_Err *,code,message) This is a simple macro that creates a new Error object in the empty Error pointer. With the code specified and a copy of the message specified. DBLK_CLONE_ERR(dest,src) This copies the values of the preexisting Error src into the already allocated dest. Objects and T_OBJR/T_OBJI Functions ----------------------------------- Well, libdatablks is really intended for use with OO systems, IO will be OO at the programming level (like MOO), the ORB is OO. Of course C doesn't have objects by itself. Libdatablks may, at some point, implement "object instances", like, real objects. Probably this would be better handled by the specific application, though. However, libdatablks does implement notional "object references", which are simple agragates in the form {int domain, int object}. The are intended to be a representative code for an object in a database of objects, like the #object-number syntax in MOO (they do, however, offer more flexibility in that the can be grouped, though the Domain code, a number of ways). The C type for object references is DBLK_ObRef. Datablk *dblk_mkobr(const DBLK_ObRef *) Create a new Datablk who's value is a copy if the ObRef. Datablk *dblk_mkgenobr(const int Domain, const int Object) Create a new Datablk with a new ObRef with the values specified. dblk_getobr(DBLK_ObRef *, const Datablk *) Load a previously allocated ObRef with the values contained in the Datablk. dblk_setobr(const DBLK_ObRef *, Datablk *) Set a Datablk's value to that of the ObRef. dblk_setgenobr(const int Domain, const int Object, Datablk *ablk) Set a Datablk's value to a new ObRef with the values specified. DBLK_INIT_OBR(DBLK_ObRef *,Domain,Object) This is a simple macro to allocate a new ObRef into an empty ObRef *. DBLK_CLONE_OBR(dest,src) This is a simple macro to copy one ObRef into another.