Пример #1
0
static char *hyphen(char *dst, const char *src, char delim) {
	const char *exp = expchck(src, delim);
	if (exp) return strcpy(dst, exp);

	char txt[TOKLEN + 1];
	sprintf(txt, ".%s.", src);
	char *txtend = txt + strlen(txt);

	uint8_t wght[TOKLEN + 1] = {0};
	for (char *s = txt; *s; ++s) {
		char *p = s;
		trie_t trie = pattern;
		while (p <= txtend && trie) {
			if (trie_child(trie, 0))
				for (char *i = s; i <= p; ++i)
					wght[i - txt] = MAX(
						wght[i - txt],
						((uint8_t *)trie_find(trie, ""))[i - s]
					);
			trie = trie_child(trie, tolower(*p++));
		}
	}

	wght[1] = wght[2] = 0;
	wght[txtend - txt - 1] = wght[txtend - txt - 2] = 0;

	char *pdst = dst;
	for (char *s = txt + 1; s < txtend - 1; *pdst++ = *s++)
		if (wght[s - txt] & 1)
			*pdst++ = delim;
	*pdst = 0;
	return dst;
}
Пример #2
0
static void falcon_cache_recursive_foreach_descendant(const trie_node_t *node,
                                                      GFunc func, gpointer udata)
{
	falcon_object_t *data = NULL;

	while (node) {
		if (trie_child(node))
			falcon_cache_recursive_foreach_descendant(trie_child(node), func,
			                                          udata);
		if ((data = trie_data(node)))
			func(data, udata);
		node = trie_next(node);
	}
}
Пример #3
0
/* 
 * Returns non-null if trie contains the specified word, otherwise
 * null.  In fact, returns the very node of the trie that represents
 * the word, if it exists.  's' must be null terminated. */
Trie* trie_contains( Trie *t, unsigned char* s ) {
  unsigned char *prefix;
  do {
    prefix = t->prefix;
    while ( prefix[0] && s[0] && prefix[0] == s[0] ) {
      ++prefix;
      ++s;
    }
    if ( prefix[0] ) {
      // node's prefix is *longer* than the word we're checking, so
      // word is not contained in trie
      return NULL;
    }

    // if we've reached the end of our word, then this node must also
    // represent the end of a trie member, if the word is contained in
    // the trie
    unsigned char c = s[0];
    if ( c == 0 ) {
      if ( t->is_end_of_string ) {
        return t;
      } else { 
        return NULL;
      }
    }
    t = trie_child( t, c, NULL );
    if ( !t ) {
      return NULL;
    }
  } while ( 1 );
}
Пример #4
0
static void recursive_print(const trie_node_t *node, guint l)
{
	guint i = 0;
	guint len = 0;

	while (node) {
		printf("%s", trie_key(node) ? trie_key(node) : "ROOT");
		if (trie_child(node)) {
			if (trie_key(node))
				len = strlen(trie_key(node)) + 2;
			printf("->");
			recursive_print(trie_child(node), l + len);
		}
		if (trie_next(node))
			printf("\n");
		for (i = 0; i < l; i++)
			printf(" ");
		node = trie_next(node);
	}
}
Пример #5
0
void falcon_cache_foreach_top(falcon_cache_t *cache, GFunc func,
                              gpointer userdata)
{
	g_return_if_fail(cache);
	g_return_if_fail(func);

	g_mutex_lock(cache->lock);
	falcon_cache_recursive_foreach_top(trie_child(cache->objects), func,
	                                   userdata);
	g_mutex_unlock(cache->lock);
}
Пример #6
0
void falcon_cache_foreach_descendant(falcon_cache_t *cache, const gchar *name,
                                     GFunc func, gpointer userdata)
{
	trie_node_t *node = NULL;
	falcon_object_t *data = NULL;

	g_return_if_fail(cache);
	g_return_if_fail(func);

	g_mutex_lock(cache->lock);
	node = trie_find(cache->objects, name);
	falcon_cache_recursive_foreach_descendant(trie_child(node), func, userdata);
	if ((data = trie_data(node)))
		func(data, userdata);
	g_mutex_unlock(cache->lock);
}
Пример #7
0
void falcon_cache_foreach_child(falcon_cache_t *cache, const gchar *name,
                                GFunc func, gpointer userdata)
{
	trie_node_t *node = NULL;
	trie_node_t *next = NULL;
	falcon_object_t *data = NULL;

	g_return_if_fail(cache);
	g_return_if_fail(func);

	g_mutex_lock(cache->lock);
	node = trie_find(cache->objects, name);
	next = trie_child(node);
	while (next) {
		if ((data = trie_data(next)))
			func(data, userdata);
		next = trie_next(next);
	}
	if ((data = trie_data(node)))
		func(data, userdata);
	g_mutex_unlock(cache->lock);
}
Пример #8
0
/* Add a word (and an optional associated data) to the trie.  's', the
 * word, will be duplicated, so the trie does assume memory
 * "ownership" of this string.  If 'data' is not null, be sure to
 * write and specify a callback function for the 'free_data_callback'
 * argument of trie_free(), so that this "user" data is freed.  If
 * word already exists in the trie, this function returns 0 and the
 * trie will not be modified.
 * 
 */
int trie_add( Trie *t, unsigned char* s, void *data ) {
  Trie *last = t;
  unsigned char prefix[MAX_WORD_LEN + 1];
  prefix[0] = 0;
  // check validity of word before (potentially) making any changes to
  // the trie, which might otherwise leave it with a partially-added
  // path (because an invalid char is found later in the word)
  if ( !_is_valid_word( s ) ) {
    return 0;
  }
  // (we could make this duplication check while we add, but this is
  // more readable)
  if ( trie_contains( t, s ) ) {
    return 0;
  }
  do {
    if ( *s == 0 || t == NULL ) {
      if ( t == NULL ) {
        // it's now time to allocate our new child node
        t = trie_new_child( last, s );
      }
      t->is_end_of_string = 1;
      t->data = data;
      return 1;
    } 
    else {
      last = t;
      Trie *child = trie_child( t, s[0], prefix );
      if ( !child ) {
        // cause logic, above, to create a new child
        t = NULL;
      } else {
        int n = 0;
        while ( prefix[n] && s[n] && prefix[n] == s[n] ) {
          ++n;
        }
        // if 's' is a prefix of child->prefix, or if 's' differs from
        // prefix at some point, then we must split the folded-path
        // child into two nodes
        if ( prefix[n] != 0 ) {
          // insert new intermediate node, breaking up a folded path
          int old_child_index = _char_to_index( child->prefix[0] );
          // set the child's prefix to the tail of the original prefix
          memmove( child->prefix, child->prefix + n, strlen( child->prefix + n ) + 1 );
          // orphan the child (for later re-parenting)
          t->children[old_child_index] = NULL;
          // insert the new intermediate child, assigning it the head
          // of the original prefix; 't' will now represent the new,
          // intermediate child
          prefix[n] = 0;
          t = trie_new_child( t, prefix );
          // make the new intermediate child the parent of the
          // original child
          _trie_alloc_children_array( t );
          t->children[_char_to_index( child->prefix[0] )] = child;
          // we now resume the normal loop logic, which will finish up
          // the initialization of our new intermediate child and then
          // return...
        } else {
          t = child;
        }
        s += n;
      }
    }
  } while ( 1 );
  return 1;
}