void list_keys_in_hash( struct hash * current, struct list * result, char * prefix ) {
    int siglen = strlen(current->sigstr);
    int prefixlen = strlen(prefix);
    char * path = malloc( ( prefixlen + siglen + 2 ) * sizeof(char) ); // Extra child char.
    strcpy( path, prefix );
    strcat( path, current->sigstr );
    path[ prefixlen + siglen + 1 ] = path[ prefixlen + siglen ] = '\0';
    char * chars_in_child = chars_in( current->child, 0, 0 );
    char child_char = '\0';
    struct hash * child_hash = NULL;
    int i = current->num_children;
    while ( i-- ) { // Recurse through all children.
        child_char = chars_in_child[i];
        if ( child_char == '\0' ) { // No keys to recurse through.
            continue;
        }
        path[ prefixlen + siglen ] = child_char; // Get the path prefix for this child.
        child_hash = charhashlookup( current->child, child_char )->data;
        list_keys_in_hash( child_hash, result, path );
    }

    // Decide if the path to this node needs to be included in the list of keys.
    if ( current->data ) {
        path[ prefixlen + siglen ] = '\0';
        append_to_list( result, (void *) path );
    }
    else {
        free(path);
    }
    free(chars_in_child);
    return;
}
struct hash_search_state hash_search( struct hash * root, char * key ) {
    struct hash * parent = NULL;
    struct hash * node = root;
    struct hash * child;
    char * str = key;
    int num_matched;
    char config;
    char parent_choice = '\0';
    char next_char = '\0';
    struct charhash * child_charhash;
    while ( node ) {
        num_matched = longest_common_prefix( str, node->sigstr, &config );
        if ( config != 'c' ) {
            break;
        }
        next_char = *( str + num_matched );
        if ( !( child_charhash = charhashlookup( node->child, next_char ) ) ) {
            break; // No child corresponding to this character.
        }
        str += ( num_matched + 1 );
        parent = node;
        node = child_charhash->data;
        parent_choice = next_char;
    }
    struct hash_search_state search_state = {
        parent,
        node,
        parent_choice,
        str,
        num_matched,
        config
    };
    return search_state;
}
void destroy_hash( struct hash * current ) {
    char * child_chars = chars_in( current->child, 0, 0 );
    int i = current->num_children;
    struct hash * child_hash;
    while ( i-- ) {
        child_hash = charhashlookup( current->child, child_chars[i] )->data;
        destroy_hash( child_hash );
    }
    free(child_chars);
    free(current->sigstr);
    destroy_charhash(current->child);
    return;
}
示例#4
0
void add_to_trie( struct trie_node * trie, char * path, char * accepting_type ) {
    struct trie_node * current_node = trie;
    struct trie_node * next_node = NULL;
    char c;
    int i;
    int path_len = strlen( path );
    for ( i = 0; i < path_len; i++ ) {
        c = path[i];
        struct  charhash * looked_up = charhashlookup( current_node->child, c );
        if ( ! looked_up ) {
            next_node = new_trie_node();
            add_to_charhash( current_node->child, c, (void *) next_node );
        }
        else {
            next_node = looked_up->data;
        }
        if ( i == path_len - 1 ) { // Last char gets accepting type.
            next_node->accepting_type = accepting_type;
        }
        current_node = next_node;
    }
    return;
}
void absorb_single_hash_child( struct hash_search_state search_state ) {

    // Figure out what character the single child is listed under.
    char * decision_char = chars_in( search_state.node->child, '\0', 0 ); // 1-char string
    struct hash * child = charhashlookup( search_state.node->child, *decision_char )->data;

    // Concatenate the decision_char and the child's sigstr onto search_state node's sigstr.
    int extension_length = strlen(child->sigstr);
    int sigstr_length = strlen(search_state.node->sigstr);
    char * new_sigstr = malloc( ( sigstr_length + 1 + extension_length ) * sizeof(char) );
    strcpy( new_sigstr, search_state.node->sigstr );
    strcat( new_sigstr, decision_char );
    strcat( new_sigstr, child->sigstr );
    free(search_state.node->sigstr);
    search_state.node->sigstr = new_sigstr;

    // Copy the child node's info.
    destroy_charhash(search_state.node->child);
    search_state.node->child = child->child;
    search_state.node->data = child->data;
    search_state.node->num_children = child->num_children;
    free(child);
    return;
}
示例#6
0
struct token * get_next_token( char * string, int start ) {
    struct token * next_token = new_token();
    if ( string[start] == '\0' ) {
	next_token->type = "end";
	next_token->first = start;
	next_token->last = start;
	return next_token;
    }
    struct trie_node * current_node = TRIE;
    struct charhash * next_node = NULL;
    int i = start;
    char input_char;
    while ( input_char = string[i] ) { // Loop characters of string.
	if ( next_node = charhashlookup( current_node->child, input_char ) ) {
	    current_node = next_node->data;
	    i = i + 1;
	}
	else { // No transition for this character.
	    if ( current_node->accepting_type ) {
		i = i - 1; // "Push" this character back on the input.
	    }
	    break;
	}
    } // End characters of string loop.

    if ( input_char == '\0' ) {
	i = i - 1;
    }
    next_token->first = start;
    next_token->last = i;
    next_token->type = current_node->accepting_type;
    if ( ! current_node->accepting_type ) {
	next_token->type = "text";
    }
    return next_token;
}
char * hashtreeprint( struct hash * current, char * prefixstr) {

    char * nextprefixstr;
    int num_children, childinfolen, childformatchars, treeformatchars;
    struct hash * nexthash;

    // Get the info string for the current node.
    char * currentinfostr = hashinfo( current, prefixstr);

    // Get a pointer to an array containing the characters in the child charhash.
    char * c = chars_in( current->child, 0, 0 );

    // Record the number of children.
    num_children = strlen(c);

    // Allocate an array of strings ( one for each child ).
    char ** childstrings = malloc( num_children * sizeof(char*) );

    if( ! childstrings ) {
        return("Out of memory!");
    }

    // Go down each branch, creating childstrings.
    int i;
    childinfolen = 0;
    nextprefixstr = malloc( 2 * sizeof(char) );
    if( ! nextprefixstr ) {
        return("Out of memory!");
    }

    childformatchars = 9; // For the <td></td>.
    nextprefixstr[1] = '\0'; // Only the first character will change.

    for( i = 0; i < num_children; i++ ) { // Loop children.
        nexthash = ( struct hash * ) charhashlookup( current->child, c[i] )->data;
        nextprefixstr[0] = c[i];

        // Recurse to the next hash.
        childstrings[i] = hashtreeprint( nexthash, nextprefixstr );

        // Increment the info length.
        childinfolen += ( strlen(childstrings[i]) + childformatchars );
    } // End children loop.

    // Prepare child info string.
    char * childinfostr = malloc((childinfolen + 1) * sizeof(char));
    if( ! childinfostr ) {
        return("Out of memory!");
    }

    *childinfostr = '\0'; // Prepare to strcat onto this.

    // Surround each child with <td> tags.
    for( i = 0; i < num_children; i++ ) { // Loop children again.
        strcat( childinfostr, "<td>" );
        strcat( childinfostr, childstrings[i] );
        strcat( childinfostr, "</td>" );
    } // End children again loop.

    // Allocate a result string, with correct length.
    treeformatchars = 149; // All table formatting.

    char * resultstr = malloc(
                           (strlen(childinfostr) +
                            strlen(currentinfostr) +
                            treeformatchars + 1) * sizeof(char) );

    if( ! resultstr ) {
        return "Out of memory!";
    }

    // Now fill out the template.
    *resultstr = '\0'; // For strcat.
    strcat(resultstr, "<table><tr align=center><td>" );
    strcat(resultstr, currentinfostr );
    strcat(resultstr, "</td></tr><tr align=center><td>" );
    strcat(resultstr, "<table cellpadding=5><tr align=center valign=top>" );
    strcat(resultstr, childinfostr );
    strcat(resultstr, "</tr></table></td></tr></table>" );

    // Free up resources allocated.
    free(childinfostr);
    free(nextprefixstr);
    free(childstrings);
    return resultstr;

} // End function hashtreeprint.