summaryrefslogblamecommitdiffstats
path: root/libsmartcols/src/line.c
blob: b982fba6d8a6df814906fc5cce7247dc86bd16fe (plain) (tree)
1
2
3
4
5



                                                          
                                                        











                                                        





                                                                             






                                          














                                               
 
                                        


                                           
                                          

                                
                       


         












































                                                                        














                                                                 
                                                                                  

                   

















                                                                               
                               












                                                              








                                                                     

























                                                                                  


























                                                                     












                                                                   




















                                                                             




                                                               
                 









                                                 


                                                    
                                     
                                   
                                   
 

                                                                           
                                 








                              
/*
 * line.c - functions for table handling at the line level
 *
 * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
 * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
 *
 * This file may be redistributed under the terms of the
 * GNU Lesser General Public License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include "smartcolsP.h"

/*
 * Note that the line is allocated without cells, the cells will be allocated
 * later when you add the line to the table. If you want to use the line
 * without table then you have to explicitly allocate the cells by
 * scols_line_alloc_cells().
 */
struct libscols_line *scols_new_line(void)
{
	struct libscols_line *ln;

	ln = calloc(1, sizeof(*ln));
	if (!ln)
		return NULL;
	ln->refcount = 1;
	INIT_LIST_HEAD(&ln->ln_lines);
	INIT_LIST_HEAD(&ln->ln_children);
	INIT_LIST_HEAD(&ln->ln_branch);
	return ln;
}

void scols_ref_line(struct libscols_line *ln)
{
	if (ln)
		ln->refcount++;
}

void scols_unref_line(struct libscols_line *ln)
{

	if (ln && --ln->refcount <= 0) {
		list_del(&ln->ln_lines);
		list_del(&ln->ln_children);

		scols_line_free_cells(ln);
		free(ln->color);
		free(ln);
		return;
	}
}

void scols_line_free_cells(struct libscols_line *ln)
{
	size_t i;

	if (!ln || !ln->cells)
		return;

	for (i = 0; i < ln->ncells; i++)
		scols_reset_cell(&ln->cells[i]);

	free(ln->cells);
	ln->ncells = 0;
	ln->cells = NULL;
}


int scols_line_alloc_cells(struct libscols_line *ln, size_t n)
{
	struct libscols_cell *ce;

	assert(ln);

	if (!ln)
		return -EINVAL;
	if (ln->ncells == n)
		return 0;

	if (!n) {
		scols_line_free_cells(ln);
		return 0;
	}

	ce = realloc(ln->cells, n * sizeof(struct libscols_cell));
	if (!ce)
		return -errno;

	if (n > ln->ncells)
		memset(ce + ln->ncells, 0,
		       (n - ln->ncells) * sizeof(struct libscols_cell));

	ln->cells = ce;
	ln->ncells = n;
	return 0;
}

int scols_line_set_userdata(struct libscols_line *ln, void *data)
{
	assert(ln);
	if (!ln)
		return -EINVAL;
	ln->userdata = data;
	return 0;
}

void *scols_line_get_userdata(struct libscols_line *ln)
{
	assert(ln);
	return ln ? ln->userdata : NULL;
}

int scols_line_remove_child(struct libscols_line *ln, struct libscols_line *child)
{
	assert(ln);
	assert(child);

	if (!ln || !child)
		return -EINVAL;
	list_del_init(&child->ln_children);
	scols_unref_line(child);

	child->parent = NULL;
	scols_unref_line(ln);
	return 0;
}

int scols_line_add_child(struct libscols_line *ln, struct libscols_line *child)
{
	assert(ln);
	assert(child);

	if (!ln || !child)
		return -EINVAL;

	/* unref old<->parent */
	if (child->parent)
		scols_line_remove_child(child->parent, child);

	/* new reference from parent to child */
	list_add_tail(&child->ln_children, &ln->ln_branch);
	scols_ref_line(child);

	/* new reference from child to parent */
	child->parent = ln;
	scols_ref_line(ln);

	return 0;
}

struct libscols_line *scols_line_get_parent(struct libscols_line *ln)
{
	assert(ln);
	return ln ? ln->parent : NULL;
}

int scols_line_has_children(struct libscols_line *ln)
{
	assert(ln);
	return ln ? !list_empty(&ln->ln_branch) : 0;
}

int scols_line_next_child(struct libscols_line *ln,
			  struct libscols_iter *itr,
			  struct libscols_line **chld)
{
	int rc = 1;

	if (!ln || !itr || !chld)
		return -EINVAL;
	*chld = NULL;

	if (!itr->head)
		SCOLS_ITER_INIT(itr, &ln->ln_branch);
	if (itr->p != itr->head) {
		SCOLS_ITER_ITERATE(itr, *chld, struct libscols_line, ln_children);
		rc = 0;
	}

	return rc;
}

/*
 * The default line color, used when cell color unspecified.
 */
int scols_line_set_color(struct libscols_line *ln, const char *color)
{
	char *p = NULL;

	assert(ln);
	if (!ln)
		return -EINVAL;
	if (color) {
		p = strdup(color);
		if (!p)
			return -ENOMEM;
	}

	free(ln->color);
	ln->color = p;
	return 0;
}

const char *scols_line_get_color(struct libscols_line *ln)
{
	assert(ln);
	return ln ? ln->color : NULL;
}

size_t scols_line_get_ncells(struct libscols_line *ln)
{
	assert(ln);
	return ln ? ln->ncells : 0;
}

struct libscols_cell *scols_line_get_cell(struct libscols_line *ln,
					  size_t n)
{
	assert(ln);

	if (!ln || n >= ln->ncells)
		return NULL;
	return &ln->cells[n];
}

/* just shortcut */
int scols_line_set_data(struct libscols_line *ln, size_t n, const char *data)
{
	struct libscols_cell *ce = scols_line_get_cell(ln, n);

	if (!ce)
		return -EINVAL;
	return scols_cell_set_data(ce, data);
}

/* just shortcut */
int scols_line_refer_data(struct libscols_line *ln, size_t n, char *data)
{
	struct libscols_cell *ce = scols_line_get_cell(ln, n);

	if (!ce)
		return -EINVAL;
	return scols_cell_refer_data(ce, data);
}

struct libscols_line *scols_copy_line(struct libscols_line *ln)
{
	struct libscols_line *ret;
	size_t i;

	assert (ln);
	if (!ln)
		return NULL;

	ret = scols_new_line();
	if (!ret)
		return NULL;
	if (scols_line_set_color(ret, ln->color))
		goto err;
	if (scols_line_alloc_cells(ret, ln->ncells))
		goto err;

	ret->userdata = ln->userdata;
	ret->ncells   = ln->ncells;
	ret->seqnum   = ln->seqnum;

	for (i = 0; i < ret->ncells; ++i) {
		if (scols_cell_copy_content(&ret->cells[i], &ln->cells[i]))
			goto err;
	}

	return ret;
err:
	scols_unref_line(ret);
	return NULL;
}