lib/eggdrop/xml.c File Reference

#include <eggdrop/eggdrop.h>

Go to the source code of this file.

Functions

const char * xml_last_error (void)
void xml_set_error (const char *err)
xml_node_txml_node_new ()
 Get a new, blank node.
xml_node_txml_node_new_named (const char *name)
 Get a new, named node.
void xml_node_free (xml_node_t *node)
 Free all memory associated with a node.
void xml_node_unlink (xml_node_t *node)
 Unlinks a XML node from a tree.
void xml_node_delete (xml_node_t *node)
 Deletes a node.
void xml_node_delete_callbacked (xml_node_t *node, void(*callback)(void *))
 Deletes a node and executes a callback function.
void xml_doc_delete (xml_node_t *root)
 Deletes an entire tree.
xml_node_txml_node_vlookup (xml_node_t *root, va_list args, int create)
xml_node_txml_node_lookup (xml_node_t *root, int create,...)
xml_node_txml_node_path_lookup (xml_node_t *root, const char *path, int index, int create)
 Get a child of a node by its name.
char * xml_node_fullname (xml_node_t *thenode)
int xml_node_get_int (int *value, xml_node_t *node,...)
int xml_node_int (xml_node_t *node, int def)
 Get an int or the default value from a node.
int xml_node_get_str (char **str, xml_node_t *node,...)
char * xml_node_str (xml_node_t *node, char *def)
 Get a string or the default value from a node.
int xml_node_set_int (int value, xml_node_t *node,...)
int xml_node_set_str (const char *str, xml_node_t *node,...)
int xml_node_get_vars (xml_node_t *node, const char *fmt,...)
int xml_node_set_vars (xml_node_t *node, const char *fmt,...)
xml_node_txml_root_element (xml_node_t *node)
void xml_node_append (xml_node_t *parent, xml_node_t *child)
 Attaches a node to a parent.
xml_attr_txml_attr_new (char *name, char *value)
 Create a new attribute.
void xml_attr_free (xml_attr_t *attr)
 Frees a node's attribute.
int xml_node_append_attr (xml_node_t *node, xml_attr_t *attr)
 Append an attribute to a node.
xml_attr_txml_attr_lookup (xml_node_t *node, const char *name)
 Searches for an attribute with a given name.
int xml_attr_int (xml_node_t *node, const char *name, int def)
 Get an int or the default value from an attribute of a node.
char * xml_attr_str (xml_node_t *node, const char *name, char *def)
 Get a string or the default value from an attribute of a node.

Variables

static const char rcsid [] = "$Id: xml.c,v 1.27 2007-08-19 19:49:17 sven Exp $"
static char * last_error = NULL


Function Documentation

void xml_attr_free ( xml_attr_t attr  ) 

Frees a node's attribute.

This will delete an attribute and free all it's memory.

Parameters:
attr The attribute to free.

Definition at line 557 of file xml.c.

References xml_attr_t::name, and xml_attr_t::value.

Referenced by xml_node_free().

00558 {
00559   if (attr->name) free(attr->name);
00560   if (attr->value) free(attr->value);
00561   free(attr);
00562 }

int xml_attr_int ( xml_node_t node,
const char *  name,
int  def 
)

Get an int or the default value from an attribute of a node.

Will return the int value of the text of a given attribute of a node. If the node does not have an attribute of the given name or the attribute does not contain text, a default value will be returned.

Parameters:
node The node to return the int from.
name The name of the attribute.
def The default value to return in case no text is available.
Returns:
Either the value of the attribute or the default value.

Definition at line 616 of file xml.c.

References xml_attr_t::value, and xml_attr_lookup().

00617 {
00618   xml_attr_t *attr = xml_attr_lookup(node, name);
00619   if (attr && attr->value) return atoi(attr->value);
00620   else return(def);
00621 }

xml_attr_t* xml_attr_lookup ( xml_node_t node,
const char *  name 
)

Searches for an attribute with a given name.

Searches all attributes of a node for a given name. If an attribute with that name is found, it's returned.

Parameters:
node The node to search.
name The name of the attribute to search for.
Returns:
The attribute if found, otherwise NULL.

Definition at line 592 of file xml.c.

References xml_node::attributes, xml_attr_t::name, xml_node::nattributes, and NULL.

Referenced by xml_attr_int(), and xml_attr_str().

00593 {
00594   int i;
00595 
00596   for (i = 0; i < node->nattributes; i++) {
00597     if (!strcasecmp(node->attributes[i]->name, name)) return(node->attributes[i]);
00598   }
00599   return(NULL);
00600 }

xml_attr_t* xml_attr_new ( char *  name,
char *  value 
)

Create a new attribute.

Creates a new attribute and fills its fields. The strings used as parameters to this function will not be dup'd but used as is. The parameters must not be NULL.

Parameters:
name The name of the attribute.
value The value of the attribute. An empty string is fine, NULL is not.
Returns:
The new attribute.

Definition at line 538 of file xml.c.

References xml_attr_t::len, xml_attr_t::name, and xml_attr_t::value.

Referenced by read_attributes().

00539 {
00540   xml_attr_t *attr;
00541 
00542   attr = malloc(sizeof(*attr));
00543   attr->name = name;
00544   attr->value = value;
00545   attr->len = strlen(value);
00546   return(attr);
00547 }

char* xml_attr_str ( xml_node_t node,
const char *  name,
char *  def 
)

Get a string or the default value from an attribute of a node.

Will return the text of a given attribute of a node as a string. If the node does not have an attribute of the given name or the attribute does not contain text, a default value will be returned.

Parameters:
node The node to return the string from.
name The name of the attribute.
def The default value to return in case no text is available.
Returns:
Either the value of the attribute or the default value.

Definition at line 637 of file xml.c.

References xml_attr_t::value, and xml_attr_lookup().

00638 {
00639   xml_attr_t *attr = xml_attr_lookup(node, name);
00640   if (attr && attr->value) return(attr->value);
00641   else return(def);
00642 }

void xml_doc_delete ( xml_node_t root  ) 

Deletes an entire tree.

This function will delete the entire tree a node is in. The node does not have to be the root of that tree, any node of the tree will do.

Parameters:
root Any node in the tree that will be deleted. Does not really have to be the root node.

Definition at line 174 of file xml.c.

References xml_node::parent, and xml_node_delete().

Referenced by user_load().

00175 {
00176   while (root->parent) root = root->parent;
00177   xml_node_delete(root);
00178 }

const char* xml_last_error ( void   ) 

Definition at line 28 of file xml.c.

References last_error.

Referenced by channel_load(), config_load(), config_save(), and user_load().

00029 {
00030   return last_error;
00031 }

void xml_node_append ( xml_node_t parent,
xml_node_t child 
)

Attaches a node to a parent.

Sets a node as a child of a parent node. This node must not have a parent! If it does, use xml_node_unlink() first!

Parameters:
parent The node that will be the parent.
child The node that will be attached to the parent.

Definition at line 498 of file xml.c.

References xml_node::children, xml_node::last_child, xml_node::name, xml_node::nchildren, xml_node::next, xml_node::next_sibling, xml_node::parent, xml_node::prev, and xml_node::prev_sibling.

Referenced by channel_save(), save_walker(), xml_node_path_lookup(), and xml_parse_node().

00499 { 
00500   xml_node_t *node;
00501 
00502   child->parent = parent;
00503   parent->nchildren++;
00504 
00505   if (!parent->children) {
00506     parent->children = child;
00507   }
00508   else {
00509     parent->last_child->next = child;
00510     child->prev = parent->last_child;
00511   }
00512 
00513   parent->last_child = child;
00514 
00515   if (!child->name) return;
00516   for (node = child->prev; node; node = node->prev) {
00517     if (node->name && !strcasecmp(node->name, child->name)) {
00518       node->next_sibling = child;
00519       child->prev_sibling = node;
00520       break;
00521     }
00522   }
00523 }

int xml_node_append_attr ( xml_node_t node,
xml_attr_t attr 
)

Append an attribute to a node.

Parameters:
node The node to appand the attribute to.
attr The attribute to append.
Returns:
Always 0.

Definition at line 573 of file xml.c.

References xml_node::attributes, and xml_node::nattributes.

Referenced by read_attributes().

00574 {
00575   node->attributes = realloc(node->attributes, sizeof(*node->attributes) * (node->nattributes+1));
00576   node->attributes[node->nattributes++] = attr;
00577   return(0);
00578 }

void xml_node_delete ( xml_node_t node  ) 

Deletes a node.

This function is a wrapper for xml_node_delete_callbacked() without a callback.

Todo:
Might be better as a macro.
Parameters:
node The node to delete.

Definition at line 131 of file xml.c.

References NULL, and xml_node_delete_callbacked().

Referenced by botnet_really_delete(), channel_free(), channel_load(), channel_save(), got_newbot(), got_nlinked(), got_version(), help_parse_file(), party_help(), user_really_delete(), user_save(), and xml_doc_delete().

00132 {
00133   xml_node_delete_callbacked(node, NULL);
00134 }

void xml_node_delete_callbacked ( xml_node_t node,
void(*)(void *)  callback 
)

Deletes a node and executes a callback function.

This function deletes a node and all of its children and attributes. For every deleted node the callback function is executed.

Parameters:
node The node to delete.
callback The callback function to execute. May be NULL.

Definition at line 146 of file xml.c.

References xml_node::children, xml_node::client_data, xml_node::next, NULL, xml_node::parent, xml_node_delete_callbacked(), xml_node_free(), and xml_node_unlink().

Referenced by config_delete_root(), config_destroy(), config_unlink_table(), xml_node_delete(), and xml_node_delete_callbacked().

00147 {
00148   xml_node_t *child, *child_next;
00149 
00150   if (node->client_data && callback) callback(node->client_data);
00151 
00152   xml_node_unlink(node);
00153 
00154   /* Delete children. */
00155   for (child = node->children; child; child = child_next) {
00156     child_next = child->next;
00157     child->parent = NULL;
00158     xml_node_delete_callbacked(child, callback);
00159   }
00160 
00161   /* Free memory taken by node. */
00162   xml_node_free(node);
00163 }

void xml_node_free ( xml_node_t node  ) 

Free all memory associated with a node.

Parameters:
node The node to be free'd.

Definition at line 74 of file xml.c.

References xml_node::attributes, xml_node::name, xml_node::nattributes, xml_node::text, and xml_attr_free().

Referenced by xml_node_delete_callbacked(), and xml_parse_node().

00075 {
00076   xml_attr_t *attr;
00077   int i;
00078 
00079   if (node->name) free(node->name);
00080   if (node->text) free(node->text);
00081   for (i = 0; i < node->nattributes; i++) {
00082     attr = node->attributes[i];
00083     xml_attr_free(attr);
00084   }
00085   if (node->attributes) free(node->attributes);
00086   free(node);
00087 }

char* xml_node_fullname ( xml_node_t thenode  ) 

Definition at line 291 of file xml.c.

References xml_node::name, and xml_node::parent.

Referenced by channel_set(), config_set_int(), and config_set_str().

00292 {
00293   xml_node_t *node;
00294   char *name, *name2;
00295   int len, total_len;
00296 
00297   len = total_len = 0;
00298   name = calloc(1, 1);
00299   for (node = thenode; node; node = node->parent) {
00300     if (!node->name) continue;
00301 
00302     /* Length of name plus the dot. */
00303     len = strlen(node->name) + 1;
00304 
00305     /* Name plus the null. */
00306     name2 = malloc(len + total_len + 1);
00307 
00308     /* Create new name. */
00309     sprintf(name2, "%s.%s", node->name, name);
00310     free(name);
00311     name = name2;
00312     total_len += len;
00313   }
00314   if (total_len > 0) name[total_len-1] = 0;
00315   return(name);
00316 }

int xml_node_get_int ( int *  value,
xml_node_t node,
  ... 
)

Definition at line 318 of file xml.c.

References NULL, xml_node::text, and xml_node_vlookup().

Referenced by channel_get_int(), config_get_int(), and xml_node_get_vars().

00319 {
00320   va_list args;
00321 
00322   va_start(args, node);
00323   node = xml_node_vlookup(node, args, 0);
00324   va_end(args);
00325   if (node && node->text) {
00326     *value = strtol(node->text, NULL, 0);
00327     return(0);
00328   }
00329   *value = 0;
00330   return(-1);
00331 }

int xml_node_get_str ( char **  str,
xml_node_t node,
  ... 
)

Definition at line 357 of file xml.c.

References NULL, xml_node::text, and xml_node_vlookup().

Referenced by botnet_get_info(), channel_get(), channel_set(), config_get_str(), help_lookup_entry(), user_get_setting(), and xml_node_get_vars().

00358 {
00359   va_list args;
00360 
00361   va_start(args, node);
00362   node = xml_node_vlookup(node, args, 0);
00363   va_end(args);
00364   if (node) {
00365     *str = node->text;
00366     return(0);
00367   }
00368   *str = NULL;
00369   return(-1);
00370 }

int xml_node_get_vars ( xml_node_t node,
const char *  fmt,
  ... 
)

Definition at line 420 of file xml.c.

References xml_node_get_int(), xml_node_get_str(), and xml_node_path_lookup().

Referenced by channel_load(), help_parse_file(), help_parse_syntax(), help_summarize_entry(), party_help(), and user_load().

00421 {
00422   va_list args;
00423   char *name, **strptr;
00424   int *intptr;
00425   xml_node_t **nodeptr;
00426 
00427   va_start(args, fmt);
00428   while (*fmt) {
00429     name = va_arg(args, char *);
00430     switch (*fmt) {
00431       case 's':
00432         strptr = va_arg(args, char **);
00433         xml_node_get_str(strptr, node, name, 0, 0);
00434         break;
00435       case 'i':
00436         intptr = va_arg(args, int *);
00437         xml_node_get_int(intptr, node, name, 0, 0);
00438         break;
00439       case 'n':
00440         nodeptr = va_arg(args, xml_node_t **);
00441         *nodeptr = xml_node_path_lookup(node, name, 0, 0);
00442         break;
00443     }
00444     fmt++;
00445   }
00446   va_end(args);
00447   return(0);
00448 }

int xml_node_int ( xml_node_t node,
int  def 
)

Get an int or the default value from a node.

Will convert the text of a given node to an int and return the value. If no node was given or the node does not contain text, a default value will be returned.

Parameters:
node The node to extract the int from.
def The default value to return in case the node does not contain text.
Returns:
Either the value from the node or the default value.

Definition at line 346 of file xml.c.

References xml_node::text.

00347 {
00348   int value;
00349   char *ptr;
00350 
00351   if (!node || !node->text) return(def);
00352   value = strtol(node->text, &ptr, 0);
00353   if (!ptr || *ptr) return(def);
00354   else return(value);
00355 }

xml_node_t* xml_node_lookup ( xml_node_t root,
int  create,
  ... 
)

Definition at line 194 of file xml.c.

References xml_node_vlookup().

Referenced by channel_load(), config_link_table(), config_unlink_table(), config_update_table(), find_setting(), help_lookup_entry(), and user_load().

00195 {
00196   va_list args;
00197   xml_node_t *node;
00198 
00199   va_start(args, create);
00200   node = xml_node_vlookup(root, args, create);
00201   va_end(args);
00202   return(node);
00203 }

xml_node_t* xml_node_new ( void   ) 

Get a new, blank node.

Returns:
The new, empty node.

Definition at line 44 of file xml.c.

Referenced by append_setting(), botnet_new(), channel_probe(), channel_save(), got_newbot(), got_nlinked(), got_version(), recving_login(), save_walker(), sending_login(), user_new(), user_save(), xml_node_new_named(), xml_node_path_lookup(), xml_parse_file(), and xml_parse_node().

00045 {
00046   xml_node_t *node;
00047 
00048   node = calloc(sizeof(*node), 1);
00049   
00050   return node;
00051 }

xml_node_t* xml_node_new_named ( const char *  name  ) 

Get a new, named node.

Parameters:
name The name of the node.
Returns:
The new, empty node.

Definition at line 61 of file xml.c.

References xml_node::name, and xml_node_new().

00062 {
00063   xml_node_t *node = xml_node_new();
00064   node->name = strdup(name);
00065   return(node);
00066 }

xml_node_t* xml_node_path_lookup ( xml_node_t root,
const char *  path,
int  index,
int  create 
)

Get a child of a node by its name.

This function searches a tree beginning with a given node and its children for a child by a given name.

This name can be very complex with serveral layers of the tree seperated by '.' and an index with "[x]. Example: "layer1.layer2[3].layer3".

Parameters:
root The node to start searching from.
path The name or path of the child to search for.
index Added to the index of every layer. Best used for a simple query without multiple layers.
create If this is non-zero and the node was not found it will be created.
Returns:
The node searched for or, if it was not found and create was zero, NULL.

Definition at line 222 of file xml.c.

References xml_node::children, xml_node::name, xml_node::next, xml_node::next_sibling, NULL, xml_node::type, XML_ELEMENT, xml_node_append(), and xml_node_new().

Referenced by xml_node_get_vars(), and xml_node_vlookup().

00223 {
00224   int thisindex, len;
00225   xml_node_t *child;
00226   const char *next;
00227   char *name, *sep, buf[512];
00228 
00229   for (; root && path; path = next) {
00230     /* Get the next path element. */
00231     sep = strchr(path, '.');
00232     if (sep) {
00233       next = sep+1;
00234       len = sep - path;
00235     }
00236     else {
00237       next = NULL;
00238       len = strlen(path);
00239     }
00240 
00241     /* If it's empty, skip it, otherwise copy it. */
00242     if (!len) continue;
00243     else if (len > sizeof(buf) - 10) {
00244       name = malloc(len+1);
00245     }
00246     else {
00247       name = buf;
00248     }
00249     memcpy(name, path, len);
00250     name[len] = 0;
00251 
00252     /* Ok, now see if there's an [index] at the end. The length
00253      * has to be at least 4, because it's like "a[x]" at least. */
00254     thisindex = 0;
00255     if (len > 3 && name[len-1] == ']') {
00256       sep = strrchr(name, '[');
00257       if (sep) {
00258         *sep = 0;
00259         name[len-1] = 0;
00260         thisindex = atoi(sep+1);
00261       }
00262     }
00263 
00264     /* If it's the last path element, add the index param. */
00265     if (!next) thisindex += index;
00266 
00267     for (child = root->children; child; child = child->next) {
00268       if (child->name && !strcasecmp(child->name, name)) break;
00269     }
00270 
00271     while (child && thisindex > 0) {
00272       thisindex--;
00273       child = child->next_sibling;
00274     }
00275 
00276     if (!child && create) {
00277       do {    
00278         child = xml_node_new();
00279         child->type = XML_ELEMENT;
00280         child->name = strdup(name);
00281         xml_node_append(root, child);
00282       } while (thisindex-- > 0);
00283     }
00284     if (name != buf) free(name);
00285 
00286     root = child;
00287   }
00288   return(root);
00289 }

int xml_node_set_int ( int  value,
xml_node_t node,
  ... 
)

Definition at line 390 of file xml.c.

References str_redup(), xml_node::text, and xml_node_vlookup().

Referenced by botnet_set_info_int(), channel_save(), config_set_int(), got_newbot(), got_nlinked(), got_version(), recving_login(), save_walker(), sending_login(), user_save(), and xml_node_set_vars().

00391 {
00392   char buf[32];
00393   va_list args;
00394 
00395   va_start(args, node);
00396   node = xml_node_vlookup(node, args, 1);
00397   va_end(args);
00398   if (!node) return(-1);
00399 
00400   snprintf(buf, sizeof(buf), "%d", value);
00401   str_redup(&node->text, buf);
00402 
00403   return(0);
00404 }

int xml_node_set_str ( const char *  str,
xml_node_t node,
  ... 
)

Definition at line 406 of file xml.c.

References str_redup(), xml_node::text, and xml_node_vlookup().

Referenced by botnet_set_info(), channel_save(), channel_set(), config_set_str(), got_newbot(), got_nlinked(), got_version(), recving_login(), save_walker(), sending_login(), user_set_setting(), and xml_node_set_vars().

00407 {
00408   va_list args;
00409 
00410   va_start(args, node);
00411   node = xml_node_vlookup(node, args, 1);
00412   va_end(args);
00413   if (!node) return(-1);
00414 
00415   str_redup(&node->text, str);
00416 
00417   return(0);
00418 }

int xml_node_set_vars ( xml_node_t node,
const char *  fmt,
  ... 
)

Definition at line 450 of file xml.c.

References xml_node_set_int(), and xml_node_set_str().

00451 {
00452   va_list args;
00453   char *name, *strval;
00454   int intval;
00455 
00456   va_start(args, fmt);
00457   while (*fmt) {
00458     name = va_arg(args, char *);
00459     switch (*fmt) {
00460       case 's':
00461         strval = va_arg(args, char *);
00462         xml_node_set_str(strval, node, name, 0, 0);
00463         break;
00464       case 'i':
00465         intval = va_arg(args, int);
00466         xml_node_set_int(intval, node, name, 0, 0);
00467         break;
00468     }
00469     fmt++;
00470   }
00471   va_end(args);
00472   return(0);
00473 }

char* xml_node_str ( xml_node_t node,
char *  def 
)

Get a string or the default value from a node.

Will return the text of a given node as a string. If no node was given or the node does not contain text, a default value will be returned.

Parameters:
node The node to return the string from.
def The default value to return in case the node does not contain text.
Returns:
Either the value from the node or the default value.

Definition at line 384 of file xml.c.

References xml_node::text.

Referenced by party_help(), and user_load().

00385 {
00386   if (!node || !node->text) return(def);
00387   else return(node->text);
00388 }

void xml_node_unlink ( xml_node_t node  ) 

Unlinks a XML node from a tree.

Removes a node from a tree. Unlinks the node from its parent and siblings, but all nodes descending from this one will still be attached.

Parameters:
node The node to unlink.

Definition at line 98 of file xml.c.

References xml_node::children, xml_node::last_child, xml_node::nchildren, xml_node::next, xml_node::next_sibling, NULL, xml_node::parent, xml_node::prev, and xml_node::prev_sibling.

Referenced by append_setting(), channel_load(), channel_save(), help_lookup_entry(), unlink_walker(), and xml_node_delete_callbacked().

00099 {
00100   xml_node_t *parent = node->parent;
00101 
00102   /* Unlink from parent. */
00103   if (parent) {
00104     parent->nchildren--;
00105     if (parent->children == node) parent->children = node->next;
00106     if (parent->last_child == node) parent->last_child = node->prev;
00107 
00108     node->parent = NULL;
00109   }
00110 
00111   /* Unlink from node list. */
00112   if (node->prev) node->prev->next = node->next;
00113   if (node->next) node->next->prev = node->prev;
00114 
00115   /* Unlink from sibling list. */
00116   if (node->prev_sibling) node->prev_sibling->next_sibling = node->next_sibling;
00117   if (node->next_sibling) node->next_sibling->prev_sibling = node->prev_sibling;
00118 }

xml_node_t* xml_node_vlookup ( xml_node_t root,
va_list  args,
int  create 
)

Definition at line 180 of file xml.c.

References xml_node_path_lookup().

Referenced by channel_get(), channel_get_int(), channel_get_node(), channel_set(), config_exists(), config_get_int(), config_get_str(), config_link_table(), config_lookup_section(), config_set_int(), config_set_str(), config_unlink_table(), config_update_table(), xml_node_get_int(), xml_node_get_str(), xml_node_lookup(), xml_node_set_int(), and xml_node_set_str().

00181 {
00182   char *path;
00183   int index;
00184 
00185   for (; root;) {
00186     path = va_arg(args, char *);
00187     if (!path) break;
00188     index = va_arg(args, int);
00189     root = xml_node_path_lookup(root, path, index, create);
00190   }
00191   return(root);
00192 }

xml_node_t* xml_root_element ( xml_node_t node  ) 

Definition at line 475 of file xml.c.

References xml_node::children, xml_node::next, NULL, xml_node::parent, xml_node::type, and XML_ELEMENT.

Referenced by xml_parse_file().

00476 {
00477    if (node == NULL) return NULL;
00478 
00479    /* Zoom up to the document. */
00480    while (node && node->parent) node = node->parent;
00481 
00482    /* Find first element. */
00483    node = node->children;
00484    while (node && node->type != XML_ELEMENT) node = node->next;
00485    return node;
00486 }

void xml_set_error ( const char *  err  ) 

Definition at line 33 of file xml.c.

References last_error, and str_redup().

Referenced by xml_parse_file(), xml_parse_node(), xml_save_file(), and xml_write_node().

00034 {
00035   str_redup(&last_error, err);
00036 }


Variable Documentation

char* last_error = NULL [static]

Definition at line 26 of file xml.c.

Referenced by xml_last_error(), and xml_set_error().

const char rcsid[] = "$Id: xml.c,v 1.27 2007-08-19 19:49:17 sven Exp $" [static]

Definition at line 21 of file xml.c.


Generated on Sun Nov 30 18:43:35 2008 for eggdrop1.9 by  doxygen 1.5.6