123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- /*
- * tree.c
- *
- * This file provides the implementation of a konf_tree class
- */
- #include "private.h"
- #include "lub/argv.h"
- #include "lub/string.h"
- #include "lub/ctype.h"
- #include <assert.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <regex.h>
- /*---------------------------------------------------------
- * PRIVATE META FUNCTIONS
- *--------------------------------------------------------- */
- static int konf_tree_compare(const void *first, const void *second)
- {
- const konf_tree_t *f = (const konf_tree_t *)first;
- const konf_tree_t *s = (const konf_tree_t *)second;
- /* Priority check */
- if (f->priority != s->priority)
- return (f->priority - s->priority);
- /* Sequence check */
- if (f->seq_num != s->seq_num)
- return (f->seq_num - s->seq_num);
- /* Sub-sequence check */
- if (f->sub_num != s->sub_num)
- return (f->sub_num - s->sub_num);
- /* Line check */
- return strcmp(f->lower_line, s->lower_line);
- }
- /*---------------------------------------------------------
- * PRIVATE METHODS
- *--------------------------------------------------------- */
- static void konf_tree_init(konf_tree_t * this, const char *line,
- unsigned short priority)
- {
- /* set up defaults */
- this->line = lub_string_dup(line);
- this->lower_line = lub_string_tolower(line);
- this->priority = priority;
- this->seq_num = 0;
- this->sub_num = KONF_ENTRY_OK;
- this->splitter = BOOL_TRUE;
- this->depth = -1;
- /* initialise the list of commands for this conf */
- this->list = lub_list_new(konf_tree_compare);
- }
- /*--------------------------------------------------------- */
- static void konf_tree_fini(konf_tree_t * this)
- {
- lub_list_node_t *iter;
- /* delete each conf held by this conf */
-
- while ((iter = lub_list__get_head(this->list))) {
- /* remove the conf from the tree */
- lub_list_del(this->list, iter);
- /* release the instance */
- konf_tree_delete((konf_tree_t *)lub_list_node__get_data(iter));
- lub_list_node_free(iter);
- }
- lub_list_free(this->list);
- /* free our memory */
- lub_string_free(this->line);
- this->line = NULL;
- lub_string_free(this->lower_line);
- this->lower_line = NULL;
- }
- /*---------------------------------------------------------
- * PUBLIC META FUNCTIONS
- *--------------------------------------------------------- */
- /*--------------------------------------------------------- */
- konf_tree_t *konf_tree_new(const char *line, unsigned short priority)
- {
- konf_tree_t *this = malloc(sizeof(konf_tree_t));
- if (this)
- konf_tree_init(this, line, priority);
- return this;
- }
- /*---------------------------------------------------------
- * PUBLIC METHODS
- *--------------------------------------------------------- */
- void konf_tree_delete(konf_tree_t * this)
- {
- konf_tree_fini(this);
- free(this);
- }
- /*--------------------------------------------------------- */
- void konf_tree_fprintf(konf_tree_t * this, FILE * stream,
- const char *pattern, int top_depth,
- bool_t seq, unsigned char prev_pri_hi)
- {
- konf_tree_t *conf;
- lub_list_node_t *iter;
- unsigned char pri = 0;
- regex_t regexp;
- if (this->line && (*(this->line) != '\0') &&
- (this->depth > top_depth)) {
- char *space = NULL;
- unsigned space_num = this->depth - top_depth - 1;
- if (space_num > 0) {
- space = malloc(space_num + 1);
- memset(space, ' ', space_num);
- space[space_num] = '\0';
- }
- if ((0 == this->depth) &&
- (this->splitter ||
- (konf_tree__get_priority_hi(this) != prev_pri_hi)))
- fprintf(stream, "!\n");
- fprintf(stream, "%s", space ? space : "");
- if (seq && (konf_tree__get_seq_num(this) != 0))
- fprintf(stream, "%u ", konf_tree__get_seq_num(this));
- fprintf(stream, "%s\n", this->line);
- free(space);
- }
- /* regexp compilation */
- if (pattern)
- regcomp(®exp, pattern, REG_EXTENDED | REG_ICASE);
- /* iterate child elements */
- for(iter = lub_list__get_head(this->list);
- iter; iter = lub_list_node__get_next(iter)) {
- conf = (konf_tree_t *)lub_list_node__get_data(iter);
- if (pattern && (0 != regexec(®exp, conf->line, 0, NULL, 0)))
- continue;
- konf_tree_fprintf(conf, stream, NULL, top_depth, seq, pri);
- pri = konf_tree__get_priority_hi(conf);
- }
- if (pattern)
- regfree(®exp);
- }
- /*-------------------------------------------------------- */
- static int normalize_seq(konf_tree_t * this, unsigned short priority)
- {
- unsigned short cnt = 1;
- konf_tree_t *conf = NULL;
- lub_list_node_t *iter;
- unsigned short cur_pri;
- /* If tree is empty */
- if (!(iter = lub_list__get_head(this->list)))
- return 0;
- /* Iterate and set dirty */
- do {
- conf = (konf_tree_t *)lub_list_node__get_data(iter);
- cur_pri = konf_tree__get_priority(conf);
- if (cur_pri > priority)
- break;
- if (cur_pri < priority)
- continue;
- if (konf_tree__get_seq_num(conf) == 0)
- continue;
- konf_tree__set_seq_num(conf, cnt++);
- } while ((iter = lub_list_node__get_next(iter)));
- return 0;
- }
- /*--------------------------------------------------------- */
- konf_tree_t *konf_tree_new_conf(konf_tree_t * this,
- const char *line, unsigned short priority,
- bool_t seq, unsigned short seq_num)
- {
- /* Allocate the memory for a new child element */
- konf_tree_t *newconf = konf_tree_new(line, priority);
- assert(newconf);
- /* Sequence */
- if (seq) {
- konf_tree__set_seq_num(newconf,
- seq_num ? seq_num : 0xffff);
- konf_tree__set_sub_num(newconf, KONF_ENTRY_NEW);
- }
- /* Insert it into the binary tree for this conf */
- lub_list_add(this->list, newconf);
- if (seq)
- normalize_seq(this, priority);
- return newconf;
- }
- /*--------------------------------------------------------- */
- konf_tree_t *konf_tree_find_conf(konf_tree_t * this,
- const char *line, unsigned short priority, unsigned short seq_num)
- {
- konf_tree_t *conf;
- lub_list_node_t *iter;
- int check_pri = 0;
- /* If list is empty */
- if (!(iter = lub_list__get_head(this->list)))
- return NULL;
- if ((0 != priority) && (0 != seq_num))
- check_pri = 1;
- /* Iterate non-empty tree */
- do {
- conf = (konf_tree_t *)lub_list_node__get_data(iter);
- if (check_pri) {
- if (priority > conf->priority)
- continue;
- if (priority < conf->priority)
- break;
- if (seq_num > conf->seq_num)
- continue;
- if (seq_num < conf->seq_num)
- break;
- }
- if (0 == lub_string_nocasecmp(conf->line, line))
- return conf;
- } while ((iter = lub_list_node__get_next(iter)));
- return NULL;
- }
- /*--------------------------------------------------------- */
- int konf_tree_del_pattern(konf_tree_t *this,
- const char *line, bool_t unique,
- const char *pattern, unsigned short priority,
- bool_t seq, unsigned short seq_num)
- {
- int res = 0;
- konf_tree_t *conf;
- lub_list_node_t *iter;
- regex_t regexp;
- int del_cnt = 0; /* how many strings were deleted */
- if (seq && (0 == priority))
- return -1;
- /* Is tree empty? */
- if (!(iter = lub_list__get_head(this->list)))
- return 0;
- /* Compile regular expression */
- regcomp(®exp, pattern, REG_EXTENDED | REG_ICASE);
- /* Iterate configuration tree */
- do {
- conf = (konf_tree_t *)lub_list_node__get_data(iter);
- if ((0 != priority) &&
- (priority != conf->priority))
- continue;
- if (seq && (seq_num != 0) &&
- (seq_num != conf->seq_num))
- continue;
- if (seq && (0 == seq_num) && (0 == conf->seq_num))
- continue;
- if (0 != regexec(®exp, conf->line, 0, NULL, 0))
- continue;
- if (unique && line && !strcmp(conf->lower_line, line)) {
- res++;
- continue;
- }
- lub_list_del(this->list, iter);
- konf_tree_delete(conf);
- del_cnt++;
- } while ((iter = lub_list_node__get_next(iter)));
- regfree(®exp);
- if (seq && (del_cnt != 0))
- normalize_seq(this, priority);
- return res;
- }
- /*--------------------------------------------------------- */
- unsigned short konf_tree__get_priority(const konf_tree_t * this)
- {
- return this->priority;
- }
- /*--------------------------------------------------------- */
- unsigned char konf_tree__get_priority_hi(const konf_tree_t * this)
- {
- return (unsigned char)(this->priority >> 8);
- }
- /*--------------------------------------------------------- */
- unsigned char konf_tree__get_priority_lo(const konf_tree_t * this)
- {
- return (unsigned char)(this->priority & 0xff);
- }
- /*--------------------------------------------------------- */
- bool_t konf_tree__get_splitter(const konf_tree_t * this)
- {
- return this->splitter;
- }
- /*--------------------------------------------------------- */
- void konf_tree__set_splitter(konf_tree_t *this, bool_t splitter)
- {
- this->splitter = splitter;
- }
- /*--------------------------------------------------------- */
- unsigned short konf_tree__get_seq_num(const konf_tree_t * this)
- {
- return this->seq_num;
- }
- /*--------------------------------------------------------- */
- void konf_tree__set_seq_num(konf_tree_t * this, unsigned short seq_num)
- {
- this->seq_num = seq_num;
- }
- /*--------------------------------------------------------- */
- unsigned short konf_tree__get_sub_num(const konf_tree_t * this)
- {
- return this->sub_num;
- }
- /*--------------------------------------------------------- */
- void konf_tree__set_sub_num(konf_tree_t * this, unsigned short sub_num)
- {
- this->sub_num = sub_num;
- }
- /*--------------------------------------------------------- */
- const char * konf_tree__get_line(const konf_tree_t * this)
- {
- return this->line;
- }
- /*--------------------------------------------------------- */
- void konf_tree__set_depth(konf_tree_t * this, int depth)
- {
- this->depth = depth;
- }
- /*--------------------------------------------------------- */
- int konf_tree__get_depth(const konf_tree_t * this)
- {
- return this->depth;
- }
|