Example #1
0
static inline void
r_add_child_check(RNode *root, guint8 *key, gpointer value, RNodeGetValueFunc value_func)
{
  guint8 *at;

  if (((at = strchr(key, '@')) != NULL))
    {
      /* there is an @ somewhere in the string */
      if ((at - key) > 0)
        {
          /* there are some literal characters before @ so add a new child till @ */
          *at = '\0';

          RNode *child = r_new_node(key, NULL);
          r_add_child(root, child);

          /* and insert the rest begining from @ under the newly created literal node */
          *at = '@';
          r_insert_node(child, at, value, value_func);
        }
      else
        {
          /* @ is the first so let's insert it simply and let insert_node handle @ */
          r_insert_node(root, key, value, value_func);
        }
    }
  else
    {
      /* either we don't care about parser or no @ in the text, so insert everything as
       * a simple literal node */
      RNode *child = r_new_node(key, value);

      r_add_child(root, child);
    }
}
Example #2
0
PDBProgram *
pdb_program_new(void)
{
  PDBProgram *self = g_new0(PDBProgram, 1);

  self->rules = r_new_node((guint8 *) "", NULL);
  self->ref_cnt = 1;
  return self;
}
Example #3
0
void
r_insert_node(RNode *root, guint8 *key, gpointer value, RNodeGetValueFunc value_func)
{
  RNode *node;
  gint keylen = strlen(key);
  gint nodelen = root->keylen;
  gint i = 0;

  if (key[0] == '@')
    {
      guint8 *end;

      if (keylen >= 2 && key[1] == '@')
        {
          /* we found and escape, so check if we already have a child with '@', or add a child like that */
          node = r_find_child_by_first_character(root, key[1]);

          if (!node)
            {
              /* no child so we create one
               * if we are at the end of the key than use value, otherwise it is just a gap node
               */
              node = r_new_node("@", (keylen == 2 ? value : NULL));
              r_add_child(root, node);
            }
          else if (keylen == 2)
            {
              /* if we are at the end of the key set the value if it is not already exists,
               * otherwise it is duplicate node
               */
              if (!node->value)
                node->value = value;
              else
                msg_error("Duplicate key in parser radix tree",
                    evt_tag_str("key", "@"),
                    evt_tag_str("value", value_func ? value_func(value) : "unknown"),
                    NULL);
            }

          /* go down building the tree if there is key left */
          if (keylen > 2)
            r_insert_node(node, key + 2, value, value_func);

        }
      else if ((keylen >= 2) && (end = strchr((const gchar *)key + 1, '@')) != NULL)
        {
          /* we are a parser node */
          *end = '\0';

          RParserNode *parser_node = r_new_pnode(key + 1);

          if (parser_node)
            {
              node = r_find_pchild(root, parser_node);

              if (!node)
                {
                  node = r_new_node(NULL, NULL);
                  node->parser = parser_node;

                  r_add_pchild(root, node);
                }
              else
                {
                  r_free_pnode_only(parser_node);
                }


              if ((end - key) < (keylen - 1))
                {
                  /* the key is not over so go on building the tree */
                  r_insert_node(node, end + 1, value, value_func);
                }
              else
                {
                  /* the key is over so set value if it is not yet set */

                  if (!node->value)
                    {
                      node->value = value;
                    }
                  else
                    {
                      /* FIXME: print parser type in string format */
                      msg_error("Duplicate parser node in radix tree",
                                evt_tag_int("type", node->parser->type),
                                evt_tag_str("name", log_msg_get_value_name(node->parser->handle, NULL)),
                                evt_tag_str("value", value_func ? value_func(value) : "unknown"),
                                NULL);
                    }
                }
            }

        }
      else
        msg_error("Key contains '@' without escaping",
                    evt_tag_str("key", key),
                    evt_tag_str("value", value_func ? value_func(value) : "unknown"),
                    NULL);
    }
  else
    {
      /* we are not starting with @ sign or we are not interested in @ at all */

      while (i < keylen && i < nodelen)
        {
          /* check if key is the same, or if it is a parser */
          if ((key[i] != root->key[i]) || (key[i] == '@'))
            break;

          i++;
        }


      if (nodelen == 0 || i == 0 || (i < keylen && i >= nodelen))
        {
          /*either at the root or we need to go down the tree on the right child */

          node = r_find_child_by_first_character(root, key[i]);

          if (node)
            {
              /* @ is always a singel node, and we also have an @ so insert us under root */
              if (key[i] == '@')
                r_insert_node(root, key + i, value, value_func);
              else
                r_insert_node(node, key + i, value, value_func);
            }
          else
            {
              r_add_child_check(root, key + i, value, value_func);
            }
        }
      else if (i == keylen && i == nodelen)
        {
          /* exact match */

          if (!root->value)
            root->value = value;
          else
            msg_error("Duplicate key in radix tree",
                        evt_tag_str("key", key),
                        evt_tag_str("value", value_func ? value_func(value) : "unknown"),
                        NULL);
        }
      else if (i > 0 && i < nodelen)
        {
          RNode *old_tree;
          guint8 *new_key;

          /* we need to split the current node */
          old_tree = r_new_node(root->key + i, root->value);
          if (root->num_children)
            {
              old_tree->children = root->children;
              old_tree->num_children = root->num_children;
              root->children = NULL;
              root->num_children = 0;
            }

          if (root->num_pchildren)
            {
              old_tree->pchildren = root->pchildren;
              old_tree->num_pchildren = root->num_pchildren;
              root->pchildren = NULL;
              root->num_pchildren = 0;
            }

          root->value = NULL;
          new_key = g_strndup(root->key, i);
          g_free(root->key);
          root->key = new_key;
          root->keylen = i;

          r_add_child(root, old_tree);

          if (i < keylen)
            {
              /* we add a new sub tree */
              r_add_child_check(root, key + i, value, value_func);
            }
          else
            {
              /* the split is us */
              root->value = value;
            }
        }
      else
        {
          /* simply a new children */
          r_add_child_check(root, key + i, value, value_func);
        }
    }
}