current stable:
0.99.6
unstable:
cvs (0.99.7)
General
  Home / News
  About
  Contact
  The Team

Obtaining
  Download
  Source Tarball
  CVS Web View
  Misc. Files

Documentation
  Introduction
The Manual
  Download [html]
  Download [pdf]
  View Online
API
  Download [html]
  View Online
Resources
  Script Examples

Developer
  Introduction
Developer Guide
  Download [html]
  Download [pdf]
  View Online
Ferite C API
  Download [html]
  View Online




Open Source Approved

SourceForge Logo
KwMap.net - browse the Keyword Map of ferite.org

[previous] Working With Variables[up][toc]Working With Objects And Classes [next]


Working With Namespaces

The next logical step would be to cover classes, but since classes are a combination of variables and functions and are, in a sense, much like namespaces, we need to do a little ground work before we delve into that subject. So in this section we'll cover how to create and delete namespaces, and how to create, access, and delete variables and how to register and delete functions, and how to find things within them.

Namespaces are created by registering them within the script. This can be done with the following function:

    FeriteNamespace *ferite_register_namespace( FeriteScript *script, char *name, FeriteNamespace *parent )
    			

The function takes three parameters; the script to register the namespace into, the name of the namespace you wish to create, and the parent in which to create the new namespace. The parent must either be a valid FeriteNamespace *. You can either find one with ferite_find_namespace(), or you can simply use script->mainns to use the top-level namespace of a script as the parent. If the register is successful, the FeriteNamespace * that refers to the new namespace is returned. The data it points to is internally allocated, so do not destroy it. If the register failed, it will return NULL.

Once you have a namespace created, you can delete it with this function:

    int ferite_delete_namespace( FeriteScript *script, FeriteNamespace *ns )
    			

This will destroy the namespace after recursivly destroying all of its children, this includes all variables, sub-namespaces, classes and functions. It currently always returns 1.

Creating and deleting namespaces is only fun for a short while. Eventually you'll want to put variables into your new namespace, and probably functions and classes as well. The next three functions will allow you to do j ust that.

    FeriteVariable *ferite_register_ns_variable( FeriteScript *script, FeriteNamespace *ns, FeriteVariable *var )
    			

This will register a variable into the namespace that you provide. If you've just recently created the namespace, you can use the FeriteNamespace * that the register function returned. Otherwise you will have to look up the FeriteNamespace * to the namespace you wish to place your variable in using the ferite_find_namespace() function. The value returned is always the same as the value passed in as the var parameter. The variable will be accessible under the new namespace according to its name stored in the FeriteVariable struct. So you might want to make sure you set it to something intelligent before you register it into a namespace.

    FeriteFunction *ferite_register_ns_function( FeriteScript *script, FeriteNamespace *ns, FeriteFunction *f )
    			

This functions registers a function into the given namespace. The return value is always the same as the value passed in as the f parameter. Again, the name of the element comes from the name field of the FeriteFunction struct. Set it before you register the function.

    FeriteClass *ferite_register_ns_class( FeriteScript *script, FeriteNamespace *ns, FeriteClass *klass )
    			

This will register a class into the given namespace. The return value is always the same as the value passed in as the klass parameter. Once again, the name of the element comes from the name field of the FeriteClass struct. Set the name before you register the class. Most of the time you will never use this as the standard way to create a class will also automatically register it, it is merely mentioned here for completness.

The next logical step is gaining access to variable, functions, and classes that are registered to namespaces. This is done by retrieving a FeriteNamespaceBucket which contains the information you desire in it's data element. The following function is used for retrieving these buckets:

    FeriteNamespaceBucket *ferite_find_namespace( FeriteScript *script, FeriteNamespace *parent, char *obj, int type )
    			

This will return a FeriteNamespaceBucket * on success, or NULL on failure. It takes a script, and a starting point as the first two parameters. The third parameter is the dot-delimited name of the object you are looking for, relative to the parent namespace given. So if you are using the root namespace (script->mainns) as your parent namespace, and wish to access mynamespace.myothernamespace.myvar, then you would pass "mynamespace.myothernamespace.myvar" as the third parameter. However, if you already have a FeriteNamespace * that refers to 'mynamespace', then you could pass that in as the parent (2nd parameter) and then access myvar by passing "myothernamespace.myvar" as the obj (3rd parameter). Lastly, if you already have the FeriteNamespace * for 'myothernamespace', then you would simply pass "myvar" as the obj. Because you are only dealing with one level of depth, you do not place a period within the obj in that instance. The fourth, and last, parameter is the type of object you are looking for. It is always one of the following defined types:

  • FENS_NS - retrieves namespaces

  • FENS_VAR - retrieves variables

  • FENS_FNC - retrieves functions

  • FENS_CLS - retrieves classes

If you choose to pass 0 to the function, you will get back the named FeriteNamespaceBucket if it exists. Using the above defines allows you to tell ferite_find_namespace what type of bucket you are looking for guaranteeing that what you get back is the correct item and type.

Again, once you have the bucket, you can access the desired value by looking in the data element. Example:

    FeriteVariable *myvar = NULL;
    FeriteNamespaceBucket *nsb = NULL;
    
    nsb = ferite_find_namespace(script, script->mainns, "mynamespace.myvar", FENS_VAR);
    
    if( NULL != nsb ){ /* we found it! */
    	myvar = (FeriteVariable *) nsb->data;
    	/* we needed to cast because nsb->data is a void * type */
    }
    			

At this point I can use myvar just like any other FeriteVarible *, because it is one! When the value of this variable is changed it will be noticble straight away within the script. It is also important to note that you much not take these variables you have obtained and return them to the script via FE_RETURN_VAR. This will cause ferite to delete the variable and leave dangling pointers. If you wish to return the variable simply return it like you would a normal c variable:

    return myvar;
    			

To get a function is the same process. Example:

    FeriteFunction *func = NULL;
    FeriteNamespaceBucket *nsb = NULL;
    
    nsb = ferite_find_namespace( script, script->mainns, "mynamespace.function", FENS_FNC );
    if( NULL != nsb ){
    	func = (FeriteFunction*)nsb->data;
    	....
    }
    			

It is good to note that within ferite's source, it is convention to call the namespace bucket variable 'nsb'.

As promised at the beginning of this section, here is how to unregister elements from namespaces:

    void ferite_delete_namespace_element_from_namespace( FeriteScript *script, FeriteNamespace *ns, char *name )
    			

This will delete the element name from the namespace ns within the script script. Be careful though, this function will not burrow down layers of namespaces to find the element you specify. So you cannot use the dot notation here, this is a deliberate design choice to stop accidental deletion of the wrong elements. You must first find the immediate parent of the element (using ferite_find_namespace()), and pass that in as the namespace ns. You can use this to delete namespaces from within namespaces as well, and in that case it will also recursively destroy the deleted namespace's contents.

So thats is all there really is to namespaces. They are an excellent form on container both in and out of scripts!



[previous] Working With Variables[up][toc]Working With Objects And Classes [next]
ferite et al © 2000-2004, Chris Ross