UI Panels: Initial refactorion into common structure

This commit is contained in:
Kaian 2016-01-29 13:45:49 +01:00
parent de373311ae
commit 2706c6f8cf
16 changed files with 405 additions and 326 deletions

View File

@ -12,7 +12,7 @@ sngrep_SOURCES+=capture_openssl.c
endif
sngrep_SOURCES+=address.c packet.c sip.c sip_call.c sip_msg.c sip_attr.c main.c
sngrep_SOURCES+=option.c group.c filter.c keybinding.c media.c setting.c rtp.c
sngrep_SOURCES+=util.c vector.c
sngrep_SOURCES+=util.c vector.c ui_panel.c
sngrep_SOURCES+=ui_manager.c ui_call_list.c ui_call_flow.c ui_call_raw.c
sngrep_SOURCES+=ui_stats.c ui_filter.c ui_save.c ui_msg_diff.c
sngrep_SOURCES+=ui_column_select.c ui_settings.c

View File

@ -68,7 +68,7 @@
/**
* Ui Structure definition for Call Flow panel
*/
ui_t ui_call_flow = {
ui_panel_t ui_call_flow = {
.type = PANEL_CALL_FLOW,
.panel = NULL,
.create = call_flow_create,
@ -81,34 +81,25 @@ ui_t ui_call_flow = {
PANEL *
call_flow_create()
{
PANEL *panel;
WINDOW *win;
int height, width;
call_flow_info_t *info;
// Create a new panel to fill all the screen
panel = new_panel(newwin(LINES, COLS, 0, 0));
PANEL *panel = new_panel(newwin(LINES, COLS, 0, 0));
// Initialize Call List specific data
info = sng_malloc(sizeof(call_flow_info_t));
// Store it into panel userptr
set_panel_userptr(panel, (void*) info);
call_flow_info_t *info = malloc(sizeof(call_flow_info_t));
memset(info, 0, sizeof(call_flow_info_t));
// Let's draw the fixed elements of the screen
win = panel_window(panel);
getmaxyx(win, height, width);
WINDOW *win = panel_window(panel);
// Calculate available printable area for messages
info->flow_win = subwin(win, height - 2 - 2 - 2, width - 2, 4, 0); // Header - Footer - Address
info->raw_width = 0; // calculated with the available space after drawing columns
info->last_msg = NULL;
info->flow_win = subwin(win, getmaxy(win) - 6, getmaxx(win) - 2, 4, 0);
// Create vectors for columns and flow arrows
info->columns = vector_create(2, 1);
vector_set_destroyer(info->columns, vector_generic_destroyer);
info->arrows = vector_create(20, 5);
vector_set_destroyer(info->arrows, vector_generic_destroyer);
// Store it into panel userptr
set_panel_userptr(panel, (void*) info);
return panel;
}
@ -121,15 +112,16 @@ call_flow_destroy(PANEL *panel)
// Free the panel information
if ((info = call_flow_info(panel))) {
// Delete panel columns
vector_destroy(info->columns);
vector_destroy_items(info->columns);
// Delete panel arrows
vector_destroy(info->arrows);
vector_destroy_items(info->arrows);
// Delete panel windows
delwin(info->flow_win);
delwin(info->raw_win);
// Delete displayed call group
call_group_destroy(info->group);
sng_free(info);
// Free panel info
free(info);
}
// Delete panel window
delwin(panel_window(panel));
@ -146,18 +138,16 @@ call_flow_info(PANEL *panel)
int
call_flow_draw(PANEL *panel)
{
call_flow_info_t *info;
WINDOW *win;
call_flow_arrow_t *arrow = NULL;
int height, width, cline = 0;
char title[256];
char callid[256];
// Get panel information
info = call_flow_info(panel);
call_flow_info_t *info = call_flow_info(panel);
// Get window of main panel
win = panel_window(panel);
WINDOW *win = panel_window(panel);
getmaxyx(win, height, width);
werase(win);
@ -1128,7 +1118,7 @@ call_flow_handle_key(PANEL *panel, int key)
int i, raw_width, height, width;
call_flow_info_t *info = call_flow_info(panel);
call_flow_arrow_t *next, *prev;
ui_t *next_panel;
ui_panel_t *next_panel;
sip_call_t *call = NULL;
int rnpag_steps = setting_get_intvalue(SETTING_CF_SCROLLSTEP);
int action = -1;

View File

@ -46,7 +46,7 @@
/**
* Ui Structure definition for Call List panel
*/
ui_t ui_call_list = {
ui_panel_t ui_call_list = {
.type = PANEL_CALL_LIST,
.panel = NULL,
.create = call_list_create,
@ -471,7 +471,7 @@ call_list_handle_key(PANEL *panel, int key)
{
int i, height, width, rnpag_steps = setting_get_intvalue(SETTING_CL_SCROLLSTEP);
call_list_info_t *info;
ui_t *next_panel;
ui_panel_t *next_panel;
sip_call_group_t *group;
int action = -1;
sip_call_t *call;

View File

@ -39,7 +39,7 @@
/**
* Ui Structure definition for Call Raw panel
*/
ui_t ui_call_raw = {
ui_panel_t ui_call_raw = {
.type = PANEL_CALL_RAW,
.panel = NULL,
.create = call_raw_create,
@ -203,7 +203,7 @@ int
call_raw_handle_key(PANEL *panel, int key)
{
call_raw_info_t *info;
ui_t *next_panel;
ui_panel_t *next_panel;
int rnpag_steps = setting_get_intvalue(SETTING_CR_SCROLLSTEP);
int action = -1;
@ -280,7 +280,7 @@ call_raw_handle_key(PANEL *panel, int key)
int
call_raw_set_group(sip_call_group_t *group)
{
ui_t *raw_panel;
ui_panel_t *raw_panel;
PANEL *panel;
call_raw_info_t *info;
@ -310,7 +310,7 @@ call_raw_set_group(sip_call_group_t *group)
int
call_raw_set_msg(sip_msg_t *msg)
{
ui_t *raw_panel;
ui_panel_t *raw_panel;
PANEL *panel;
call_raw_info_t *info;

View File

@ -38,7 +38,7 @@
/**
* Ui Structure definition for Message Diff panel
*/
ui_t ui_column_select = {
ui_panel_t ui_column_select = {
.type = PANEL_COLUMN_SELECT,
.panel = NULL,
.create = column_select_create,

View File

@ -40,7 +40,7 @@
/**
* Ui Structure definition for Filter panel
*/
ui_t ui_filter = {
ui_panel_t ui_filter = {
.type = PANEL_FILTER,
.panel = NULL,
.create = filter_create,

View File

@ -51,7 +51,7 @@
* and pointer to their main functions.
*/
static ui_t *panel_pool[] = {
static ui_panel_t *panel_pool[] = {
&ui_call_list,
&ui_call_flow,
&ui_call_raw,
@ -150,128 +150,17 @@ ncurses_deinit()
endwin();
}
ui_t *
ui_create(ui_t *ui)
{
// If ui has no panel
if (!ui_get_panel(ui)) {
// Create the new panel for this ui
if (ui->create) {
ui->panel = ui->create();
}
}
// And return it
return ui;
}
ui_t *
ui_panel_t *
ui_create_panel(enum panel_types type)
{
// Find the panel of given type and create it
return ui_create(ui_find_by_type(type));
}
void
ui_destroy(ui_t *ui)
{
// If there is no ui panel, we're done
if (!ui || !ui->panel)
return;
// Hide this panel before destroying
hide_panel(ui->panel);
// If panel has a destructor function use it
if (ui->destroy)
ui->destroy(ui->panel);
// Initialize panel pointer
ui->panel = NULL;
}
PANEL *
ui_get_panel(ui_t *ui)
{
// Return panel pointer of ui struct
return (ui) ? ui->panel : NULL;
}
int
ui_draw_panel(ui_t *ui)
{
PANEL *panel = NULL;
int ret = 0;
//! Sanity check, this should not happen
if (!ui)
return -1;
// Get ui panel pointer
if (!(panel = ui_get_panel(ui)))
return -1;
// Set character input timeout 200 ms
halfdelay(REFRESHTHSECS);
// Avoid parsing any packet while UI is being drawn
capture_lock();
// Request the panel to draw on the scren
if (ui->draw) {
ret = ui->draw(panel);
} else {
touchwin(panel_window(panel));
}
// Continue parsing packets
capture_unlock();
return ret;
}
int
ui_resize_panel(ui_t *ui)
{
int ret = 0;
//! Sanity check, this should not happen
if (!ui)
return -1;
// Notify the panel screen size has changed
if (ui->resize) {
ret = ui->resize(ui_get_panel(ui));
}
return ret;
}
void
ui_help(ui_t *ui)
{
// Disable input timeout
nocbreak();
cbreak();
// If current ui has help function
if (ui->help) {
ui->help(ui_get_panel(ui));
}
}
int
ui_handle_key(ui_t *ui, int key)
{
int ret = 0;
// Avoid parsing any packet while key is being handled
capture_lock();
if (ui->handle_key)
ret = ui->handle_key(ui_get_panel(ui), key);
// Continue parsing packets
capture_unlock();
return ret;
}
ui_t *
ui_panel_t *
ui_find_by_panel(PANEL *panel)
{
int i;
@ -283,7 +172,7 @@ ui_find_by_panel(PANEL *panel)
return NULL;
}
ui_t *
ui_panel_t *
ui_find_by_type(enum panel_types type)
{
int i;
@ -298,7 +187,7 @@ ui_find_by_type(enum panel_types type)
int
wait_for_input()
{
ui_t *ui;
ui_panel_t *ui;
WINDOW *win;
PANEL *panel;
@ -307,9 +196,18 @@ wait_for_input()
// Get panel interface structure
ui = ui_find_by_panel(panel);
// Set character input timeout 200 ms
halfdelay(REFRESHTHSECS);
// Avoid parsing any packet while UI is being drawn
capture_lock();
// Redraw this panel
if (ui_draw_panel(ui) != 0)
if (ui_draw_panel(ui) != 0) {
capture_unlock();
return -1;
}
capture_unlock();
// Update panel stack
update_panels();
@ -330,10 +228,13 @@ wait_for_input()
continue;
// Check if current panel has custom bindings for that key
capture_lock();
if ((c = ui_handle_key(ui, c)) == 0) {
capture_unlock();
// Key has been handled by panel
continue;
}
capture_unlock();
// Key not handled by UI, try default handler
default_handle_key(ui, c);
@ -343,7 +244,7 @@ wait_for_input()
}
int
default_handle_key(ui_t *ui, int key)
default_handle_key(ui_panel_t *ui, int key)
{
int action = -1;

View File

@ -36,14 +36,7 @@
#ifndef __SNGREP_UI_MANAGER_H
#define __SNGREP_UI_MANAGER_H
#include "config.h"
#ifdef WITH_UNICODE
#define _X_OPEN_SOURCE_EXTENDED
#include <ncursesw/ncurses.h>
#else
#include <ncurses.h>
#endif
#include <panel.h>
#include <form.h>
#include "ui_panel.h"
#include "sip.h"
#include "group.h"
#include "keybinding.h"
@ -55,40 +48,6 @@
#define DIALOG_MAX_WIDTH 100
#define DIALOG_MIN_WIDTH 40
//! Shorter declaration of ui structure
typedef struct ui ui_t;
/**
* @brief Panel information structure
*
* This struct contains the panel related data, including
* a pointer to the function that manages its drawing
*/
struct ui {
//! Panel Type @see panel_types enum
int type;
//! The actual ncurses panel pointer
PANEL *panel;
//! Constructor for this panel
PANEL *
(*create)();
//! Destroy current panel
void
(*destroy)(PANEL *);
//! Request the panel to redraw its data
int
(*draw)(PANEL*);
//! Notifies the panel the screen has changed
int
(*resize)(PANEL*);
//! Handle a custom keybind on this panel
int
(*handle_key)(PANEL*, int key);
//! Show help window for this panel (if any)
int
(*help)(PANEL *);
};
/**
* @brief Enum for available color pairs
*/
@ -116,46 +75,18 @@ enum sngrep_colors_pairs {
// Used to configure color pairs only with fg color
#define COLOR_DEFAULT -1
/**
* @brief Enum for available panel types
*
* Mostly used for managing keybindings and offloop ui refresh
*/
enum panel_types {
//! Call List ui screen
PANEL_CALL_LIST = 0,
//! Call-Flow ui screen
PANEL_CALL_FLOW,
//! Raw SIP messages ui screen
PANEL_CALL_RAW,
//! Filters panel
PANEL_FILTER,
//! Save to pcap panel
PANEL_SAVE,
//! Message comprare
PANEL_MSG_DIFF,
//! Column selector panel
PANEL_COLUMN_SELECT,
//! Settings panel
PANEL_SETTINGS,
//! Stats panel
PANEL_STATS,
//! Panel Counter
PANEL_COUNT,
};
/**
* Define existing panels
*/
extern ui_t ui_call_list;
extern ui_t ui_call_flow;
extern ui_t ui_call_raw;
extern ui_t ui_filter;
extern ui_t ui_save;
extern ui_t ui_msg_diff;
extern ui_t ui_column_select;
extern ui_t ui_settings;
extern ui_t ui_stats;
extern ui_panel_t ui_call_list;
extern ui_panel_t ui_call_flow;
extern ui_panel_t ui_call_raw;
extern ui_panel_t ui_filter;
extern ui_panel_t ui_save;
extern ui_panel_t ui_msg_diff;
extern ui_panel_t ui_column_select;
extern ui_panel_t ui_settings;
extern ui_panel_t ui_stats;
/**
* @brief Initialize ncurses mode
@ -177,17 +108,6 @@ ncurses_init();
void
ncurses_deinit();
/**
* @brief Create a panel structure
*
* Create a ncurses panel associated to the given ui
* This function is a small wrapper for panel create function
*
* @param ui UI structure
* @return the ui structure with the panel pointer created
*/
ui_t *
ui_create(ui_t *ui);
/**
* @brief Create a panel of a given type
@ -198,93 +118,19 @@ ui_create(ui_t *ui);
* @param type Panel Type
* @return the ui structure with the panel pointer created*
*/
ui_t *
ui_panel_t *
ui_create_panel(enum panel_types type);
/**
* @brief Destroy a panel structure
*
* Removes the panel associatet to the given ui and free
* its memory. Most part of this task is done in the custom
* destroy function of the panel.
*
* @param ui UI structure
*/
void
ui_destroy(ui_t *ui);
/**
* @brief Get panel pointer from an ui element
*
* Basic getter to get the Ncurses PANEL pointer
* from ui structure. Use this instead of accessing
* directly to the pointer.
*
* @param ui UI structure
* @return ncurses panel pointer of given UI
*/
PANEL *
ui_get_panel(ui_t *ui);
/**
* @brief Redrawn current ui
*
* This function acts as wrapper to custom ui draw functions
* with some checks
*
* @param ui UI structure
* @return 0 if ui has been drawn, -1 otherwise
*/
int
ui_resize_panel(ui_t *ui);
/**
* @brief Notifies current ui the screen size has changed
*
* This function acts as wrapper to custom ui resize functions
* with some checks
*
* @param ui UI structure
* @return 0 if ui has been resize, -1 otherwise
*/
int
ui_draw_panel(ui_t *ui);
/**
* @brief Show help screen from current UI (if any)
*
* This function will display the help screen for given
* ui if exits.
* All help screens exits after any character input
*
* @param ui UI structure
*/
void
ui_help(ui_t *ui);
/**
* @brief Handle key inputs on given UI
*
* This function will pass the input key sequence
* to the given UI. This will only happen if the key
* sequence don't match any of the general keybindings
*
* @param ui UI structure
* @param key keycode sequence of the pressed keys and mods
*/
int
ui_handle_key(ui_t *ui, int key);
/**
* @brief Find a ui from its pannel pointer
*/
ui_t *
ui_panel_t *
ui_find_by_panel(PANEL *panel);
/**
* @brief Find a ui form its panel id
*/
ui_t *
ui_panel_t *
ui_find_by_type(enum panel_types type);
/**
@ -307,7 +153,7 @@ wait_for_input();
* @param key key pressed by user
*/
int
default_handle_key(ui_t *ui, int key);
default_handle_key(ui_panel_t *ui, int key);
/**
* @brief Draw a box around passed windows

View File

@ -55,7 +55,7 @@
/**
* Ui Structure definition for Message Diff panel
*/
ui_t ui_msg_diff = {
ui_panel_t ui_msg_diff = {
.type = PANEL_MSG_DIFF,
.panel = NULL,
.create = msg_diff_create,

127
src/curses/ui_panel.c Normal file
View File

@ -0,0 +1,127 @@
/**************************************************************************
**
** sngrep - SIP Messages flow viewer
**
** Copyright (C) 2013-2016 Ivan Alonso (Kaian)
** Copyright (C) 2013-2016 Irontec SL. All rights reserved.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
/**
* @file ui_panel.c
* @author Ivan Alonso [aka Kaian] <kaian@irontec.com>
*
* @brief Source of functions defined in ui_panel.h
*/
#include "config.h"
#include "ui_panel.h"
ui_panel_t *
ui_create(ui_panel_t *ui)
{
// If ui has no panel
if (!ui->panel) {
// Create the new panel for this ui
if (ui->create) {
ui->panel = ui->create();
}
}
// And return it
return ui;
}
void
ui_destroy(ui_panel_t *ui)
{
// If there is no ui panel, we're done
if (!ui || !ui->panel)
return;
// Hide this panel before destroying
hide_panel(ui->panel);
// If panel has a destructor function use it
if (ui->destroy) {
ui->destroy(ui->panel);
}
// Initialize panel pointer
ui->panel = NULL;
}
PANEL *
ui_get_panel(ui_panel_t *ui)
{
// Return panel pointer of ui struct
return (ui) ? ui->panel : NULL;
}
int
ui_draw_panel(ui_panel_t *ui)
{
//! Sanity check, this should not happen
if (!ui || !ui->panel)
return -1;
// Request the panel to draw on the scren
if (ui->draw) {
return ui->draw(ui->panel);
} else {
touchwin(ui->win);
}
return 0;
}
int
ui_resize_panel(ui_panel_t *ui)
{
//! Sanity check, this should not happen
if (!ui)
return -1;
// Notify the panel screen size has changed
if (ui->resize) {
return ui->resize(ui->panel);
}
return 0;
}
void
ui_help(ui_panel_t *ui)
{
// Disable input timeout
nocbreak();
cbreak();
// If current ui has help function
if (ui->help) {
ui->help(ui->panel);
}
}
int
ui_handle_key(ui_panel_t *ui, int key)
{
if (ui->handle_key) {
return ui->handle_key(ui->panel, key);
}
return 0;
}

192
src/curses/ui_panel.h Normal file
View File

@ -0,0 +1,192 @@
/**************************************************************************
**
** sngrep - SIP Messages flow viewer
**
** Copyright (C) 2013-2016 Ivan Alonso (Kaian)
** Copyright (C) 2013-2016 Irontec SL. All rights reserved.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
/**
* @file u_panel.h
* @author Ivan Alonso [aka Kaian] <kaian@irontec.com>
*
* @brief Common process for all Interface panels
*
* This file contains common functions shared by all panels.
*/
#ifndef __SNGREP_UI_PANEL_H
#define __SNGREP_UI_PANEL_H
#ifdef WITH_UNICODE
#define _X_OPEN_SOURCE_EXTENDED
#include <ncursesw/ncurses.h>
#else
#include <ncurses.h>
#endif
#include <panel.h>
#include <form.h>
/**
* @brief Enum for available panel types
*
* Mostly used for managing keybindings and offloop ui refresh
*/
enum panel_types {
//! Call List ui screen
PANEL_CALL_LIST = 0,
//! Call-Flow ui screen
PANEL_CALL_FLOW,
//! Raw SIP messages ui screen
PANEL_CALL_RAW,
//! Filters panel
PANEL_FILTER,
//! Save to pcap panel
PANEL_SAVE,
//! Message comprare
PANEL_MSG_DIFF,
//! Column selector panel
PANEL_COLUMN_SELECT,
//! Settings panel
PANEL_SETTINGS,
//! Stats panel
PANEL_STATS,
//! Panel Counter
PANEL_COUNT,
};
//! Shorter declaration of ui structure
typedef struct ui_panel ui_panel_t;
/**
* @brief Panel information structure
*
* This struct contains the panel related data, including
* a pointer to the function that manages its drawing
*/
struct ui_panel {
//! Curses panel pointer
PANEL *panel;
//! Window for the curses panel
WINDOW *win;
//! Height of the curses window
int height;
//! Width of the curses window
int width;
//! Panel Type @see panel_types enum
enum panel_types type;
//! Constructor for this panel
PANEL* (*create)();
//! Destroy current panel
void (*destroy)(PANEL *);
//! Request the panel to redraw its data
int (*draw)(PANEL*);
//! Notifies the panel the screen has changed
int (*resize)(PANEL*);
//! Handle a custom keybind on this panel
int (*handle_key)(PANEL*, int key);
//! Show help window for this panel (if any)
int (*help)(PANEL *);
};
/**
* @brief Create a panel structure
*
* Create a ncurses panel associated to the given ui
* This function is a small wrapper for panel create function
*
* @param ui UI structure
* @return the ui structure with the panel pointer created
*/
ui_panel_t *
ui_create(ui_panel_t *ui);
/**
* @brief Destroy a panel structure
*
* Removes the panel associatet to the given ui and free
* its memory. Most part of this task is done in the custom
* destroy function of the panel.
*
* @param ui UI structure
*/
void
ui_destroy(ui_panel_t *ui);
/**
* @brief Get panel pointer from an ui element
*
* Basic getter to get the Ncurses PANEL pointer
* from ui structure. Use this instead of accessing
* directly to the pointer.
*
* @param ui UI structure
* @return ncurses panel pointer of given UI
*/
PANEL *
ui_get_panel(ui_panel_t *ui);
/**
* @brief Redrawn current ui
*
* This function acts as wrapper to custom ui draw functions
* with some checks
*
* @param ui UI structure
* @return 0 if ui has been drawn, -1 otherwise
*/
int
ui_resize_panel(ui_panel_t *ui);
/**
* @brief Notifies current ui the screen size has changed
*
* This function acts as wrapper to custom ui resize functions
* with some checks
*
* @param ui UI structure
* @return 0 if ui has been resize, -1 otherwise
*/
int
ui_draw_panel(ui_panel_t *ui);
/**
* @brief Show help screen from current UI (if any)
*
* This function will display the help screen for given
* ui if exits.
* All help screens exits after any character input
*
* @param ui UI structure
*/
void
ui_help(ui_panel_t *ui);
/**
* @brief Handle key inputs on given UI
*
* This function will pass the input key sequence
* to the given UI. This will only happen if the key
* sequence don't match any of the general keybindings
*
* @param ui UI structure
* @param key keycode sequence of the pressed keys and mods
*/
int
ui_handle_key(ui_panel_t *ui, int key);
#endif /* __SNGREP_UI_PANEL_H */

View File

@ -41,7 +41,7 @@
/**
* Ui Structure definition for Save panel
*/
ui_t ui_save = {
ui_panel_t ui_save = {
.type = PANEL_SAVE,
.panel = NULL,
.create = save_create,

View File

@ -35,7 +35,7 @@
/**
* Ui Structure definition for Settings panel
*/
ui_t ui_settings = {
ui_panel_t ui_settings = {
.type = PANEL_SETTINGS,
.panel = NULL,
.create = settings_create,

View File

@ -61,7 +61,7 @@
/**
* Ui Structure definition for Stats panel
*/
ui_t ui_stats = {
ui_panel_t ui_stats = {
.type = PANEL_STATS,
.panel = NULL,
.create = stats_create,

View File

@ -57,6 +57,23 @@ vector_destroy(vector_t *vector)
sng_free(vector);
}
void
vector_destroy_items(vector_t *vector)
{
int i;
// Nothing to free. Done
if (!vector) return;
// If vector contains items
if (vector->count) {
for (i = 0; i < vector->count; i++) {
free(vector->list[i]);
}
free(vector->list);
}
free(vector);
}
vector_t *
vector_clone(vector_t *original)

View File

@ -81,6 +81,12 @@ vector_create(int limit, int step);
void
vector_destroy(vector_t *vector);
/**
* @brief Free all vector items and memory
*/
void
vector_destroy_items(vector_t *vector);
/**
* @brief Clone a vector container
*