文章仅供个人记录使用
c语言个人打印函数及红黑树的增删改查实例记录,红黑树的移植在上一章已经描述过了,主要记录一下函数可变参的处理
/********************************************************************************************************
/ Vicon OS-I
/ The Linux-app Wireless manager
/
/
/ (c) Copyright 2019-2023; Micrium, Inc.; ShenZhen, FL
/ All rights reserved. You may obtain a copy of the License at:.
/
/ huguidong@me.com
/
/ File : MacDr.c
/ Version : V1.0.0
/ (c) : Doon < huguidong@me.com >
/ Date : 2020-January 15 Wednesday
/
/ Platform : Mipsel-Openwrt
/ Mode : Thread mode
/ Toolchain : Source Insight 4.0
/ Desc : Machine Driver .
********************************************************************************************************/
#include "MacDr.h"
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
/*
************************************************************************************************************************
* System driver entrance
*
* Description : System driver's interface .
*
* Entrance :
mytree the red-black tree root.
-------------
dev_rb_insert add some node to the device tree
-------------
dev_rb_find find some node from the device tree
-------------
dev_rb_delete delete some node from the device tree
-------------
dev_rb_destory destory the whole tree.
-------------
************************************************************************************************************************
*/
/*
*
* x point
*
* px px
* / /
* x y
* / \ --(left rotate)--> / \ #
* lx y x ry
* / \ / \
* ly ry lx ly
*
*
*/
/*
*
* y point
*
* py py
* / /
* y x
* / \ --(right rotate)--> / \ #
* x ry lx y
* / \ / \ #
* lx rx rx ry
*
*/
struct rb_root mytree;
/**
*@des: create a user node of rbtrees
*/
dev_rb_t *
create_dev_node( struct dev_info *dev_info )
{
dev_rb_t *node;
node = ( dev_rb_t* )malloc( sizeof( dev_rb_t ) );
if( node )
{
memset( node , 0 ,sizeof(dev_rb_t) );
memcpy( (char *)&node->info, dev_info , sizeof( struct dev_info ) );
return node;
}
else return NULL;
}
/**
*@des: find the user node.
*/
struct dev_info *
dev_rb_find( struct rb_root *root , char *mac )
{
struct rb_node *node = root->rb_node;
dev_rb_t *goal_node = NULL;
int res = 0;
while( node )
{
goal_node = rb_entry( node , dev_rb_t , node );
res = strcmp( goal_node->info.mac_addr , mac );
if( res < 0 ){
node = node->rb_left;
}else if( res > 0 ){
node = node->rb_right;
}else{
return &goal_node->info;
}
}
return NULL;
}
/**
*@des: insert a user node.
*/
int
dev_rb_insert( struct rb_root *root , struct dev_info *dev_info )
{
struct rb_node **new = &(root->rb_node);
struct rb_node *parent = NULL;
dev_rb_t *goal_node = NULL;
int res = 0;
while( *new )
{
parent = *new;
goal_node = rb_entry( *new , dev_rb_t , node );
res = strcmp( goal_node->info.mac_addr , dev_info->mac_addr );
if( res < 0 ){
new = &(( *new )->rb_left );
}else if( res > 0 ){
new = &(( *new )->rb_right );
}else{
return 0;
}
}
/* create red-black tree node */
goal_node = create_dev_node( dev_info );
if( goal_node )
{
// add new node
rb_link_node( &goal_node->node ,parent , new );
// rebalence red-black tree
rb_insert_color( &goal_node->node , root );
return 0; /* < success > */
}else return -1; /* < failed > */
}
/**
*@des: delete single node
*/
int
dev_rb_delete( struct rb_root *root , char *mac )
{
dev_rb_t *goal_node;
// Here changed the return of rb find . so we should offset the struct
goal_node = rb_entry( dev_rb_find( root , mac ) , dev_rb_t , info );
if( goal_node )
{
rb_erase( &goal_node->node , root );
free( goal_node );
return 0; /* < success > */
}else return -1; /* < failed > */
}
/**
*@des: destory whole tree
*/
void
dev_rb_destory( struct rb_root *root )
{
struct rb_node *node = NULL, *tmp_node = NULL;
dev_rb_t *goal_node = NULL;
for( node = rb_first(root) ; node ; )
{
tmp_node = rb_next( node );
goal_node = rb_entry( node , dev_rb_t , node );
rb_erase( node , root );
free( goal_node );
node = tmp_node;
}
}
/*
************************************************************************************************************************
* System debug entrance
*
* Description : System debug logo print .
*
* Entrance :
logo_output the system output root.
-------------
************************************************************************************************************************
*/
static char *lvl_names[] = {
"non", "crt", "err", "wrn", "inf", "dbg", "flw"
};
const char *lvl_color[] = {
"[0m", "[1;31m", "[1;31m", "[1;35m", "[1;33m", "[1;36m", "[1;34m"
};
void
my_printf(const char *fmt, ... )
{
va_list args;
va_start( args , fmt );
vprintf( fmt , args );
va_end( args );
fflush( stdout );
}
void
logo_output( unsigned char level , const char *fmt , ... )
{
va_list args;
va_start( args , fmt );
my_printf( "%s%s", "\033" , lvl_color[level] );
my_printf( "[%s] %s(%d): " , lvl_names[level] , __FILE__ , __LINE__ );
vprintf( fmt , args );
my_printf( "%s\r\n", "\033[0m");
va_end( args );
fflush( stdout );
}
struct SysBox Sysbox = {
.drv_api = {
.root = &mytree,
.find = dev_rb_find,
.insert = dev_rb_insert,
.delete = dev_rb_delete,
.destory = dev_rb_destory
},
.output = {
.print = logo_output,
},
};
/******************* (C) COPYRIGHT 2020 Doon****************END OF FILE****/
系统盒子接口如下:
struct SysBox{
struct{
/* Device's root node */
struct rb_root *root;
/* look for someone */
struct dev_info *(*find)( struct rb_root *root , char *mac );
/* Insert node */
int (*insert)( struct rb_root *root , struct dev_info *dev_info );
/* Delete node */
int (*delete)( struct rb_root *root , char *mac );
/* Destory whole tree */
void (*destory)( struct rb_root *root );
}drv_api;
struct{
void (*print)( unsigned char level , const char *fmt , ... )__attribute__ ((format (printf, 2, 3)));
}output;
};
测试代码如下:
struct dev_info test,*test1;
int rest,i;
Sysbox.output.print( LOG_NONE_LEVEL , "%s" , "LOG_NONE_LEVEL" );
Sysbox.output.print( LOG_CRIT_LEVEL , "%s" , "LOG_CRIT_LEVEL" );
Sysbox.output.print( LOG_ERR_LEVEL , "%s" , "LOG_ERR_LEVEL" );
Sysbox.output.print( LOG_WARNING_LEVEL , "%s" , "LOG_WARNING_LEVEL" );
Sysbox.output.print( LOG_INFO_LEVEL , "%s" , "LOG_INFO_LEVEL" );
Sysbox.output.print( LOG_DEBUG_LEVEL , "%s" , "LOG_DEBUG_LEVEL" );
Sysbox.output.print( LOG_FLOW_LEVEL , "%s" , "LOG_FLOW_LEVEL" );
for( i = 0 ; i < 10 ; i++ )
{
sprintf( test.mac_addr , "0123456789-%d" , i + 1 );
rest = Sysbox.drv_api.insert( Sysbox.drv_api.root , &test );
if( rest ) Sysbox.output.print( LOG_WARNING_LEVEL , "insert %s failed" , test.mac_addr );
else Sysbox.output.print( LOG_DEBUG_LEVEL , "insert %s success" , test.mac_addr );
}
/* find the first one */
test1 = Sysbox.drv_api.find( Sysbox.drv_api.root , "0123456789-1" );
if( test1 != NULL ) Sysbox.output.print( LOG_DEBUG_LEVEL , "find [%s]" , test1->mac_addr );
else Sysbox.output.print( LOG_WARNING_LEVEL , "can't find-1" );
/* delete the first one */
rest = Sysbox.drv_api.delete( Sysbox.drv_api.root , "0123456789-1" );
if( rest ) Sysbox.output.print( LOG_WARNING_LEVEL , "delete 0123456789-1 failed" );
else Sysbox.output.print( LOG_DEBUG_LEVEL , "delete 0123456789-1 success" );
/* find the first one again */
test1 = Sysbox.drv_api.find( Sysbox.drv_api.root , "0123456789-1" );
if( test1 != NULL ) Sysbox.output.print( LOG_DEBUG_LEVEL , "find [%s]" , test1->mac_addr );
else Sysbox.output.print( LOG_WARNING_LEVEL , "can't find-1" );
以及通过mqtt的触发发送
int
MQ_Test( const char *buff )
{
cJSON *root,*devlist,*dev;
struct rb_node *node;
char *endpoint , *l_poJson;
root = cJSON_CreateObject();
if( root )
{
cJSON_AddStringToObject( root , "Code" , "200" );
cJSON_AddStringToObject( root , "Cmd" , "Test" );
devlist = cJSON_CreateArray();
cJSON_AddItemToObject( root , "RbTree" , devlist );
for( node = rb_first( Sysbox.drv_api.root ) ; node ; node = rb_next( node ) )
{
//Sysbox.output.print( LOG_INFO_LEVEL , "Mac[%s]" , rb_entry( node , dev_rb_t , node )->info.mac_addr );
dev = cJSON_CreateObject();
cJSON_AddItemToArray( devlist , dev );
cJSON_AddStringToObject( dev , "mac_addr" , rb_entry( node , dev_rb_t , node )->info.mac_addr );
}
l_poJson = cJSON_PrintUnformatted( root );
KS_MQTT_Publish( l_poJson );
cJSON_Delete( root );
free( l_poJson );
return 0;
}
}
好的,接下来看看效果:
整体来说也还行~~不过目前仅仅是个demo,后续会把打印等级开关,重定向到文件等等补齐。json的打印未贴出~有兴趣的可以去阿里给的MQTT源码里找。
收工!