验证中...
Languages: C/C++
Categories: 常用工具包
Latest update 2019-11-09 20:04
tbox
Raw Copy
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <assert.h>
#include <stdarg.h>
#include <yaml.h>
#include <tbox/tbox.h>
#define MY_MALLOC malloc
#define MY_FREE free
typedef enum {
TYPE_NON,
TYPE_MAP,
TYPE_LIST,
TYPE_SCALAR
} TYPE;
typedef struct {
TYPE type;
void* data;
} Node;
typedef struct {
TYPE type;
Node* left;
Node* right;
} Node_Map_Pair;
typedef struct {
TYPE type;
tb_hash_map_ref_t data;
uint8_t is_left;
Node_Map_Pair* pair;
} Node_Map;
typedef struct {
TYPE type;
tb_vector_ref_t data;
} Node_List;
typedef struct {
TYPE type;
tb_string_ref_t data;
} Node_Scalar;
tb_void_t Node_free_( tb_element_ref_t element, tb_pointer_t buff );
tb_void_t
Node_Map_Pair_free( tb_element_ref_t element, tb_pointer_t buff ) {
Node_Map_Pair* node = *( Node_Map_Pair** )buff;
Node_free_( NULL, &node->left );
Node_free_( NULL, &node->right );
MY_FREE( node );
}
// Key 是 c string,value 是 Node_Map_Pair*,使用 get 时,返回值要注意
Node_Map*
Node_Map_Create() {
Node_Map* node = ( Node_Map* )MY_MALLOC( sizeof( Node_Map ) );
node->type = TYPE_MAP;
node->data = tb_hash_map_init(
0,
tb_element_str( true ),
tb_element_ptr( Node_Map_Pair_free, NULL )
);
node->is_left = true;
node->pair = NULL;
return node;
}
#define Node_Map_Destroy(x) do{ Node_Map_Destroy_( ( Node_Map* )x ); x = NULL; }while(0)
void
Node_Map_Destroy_( Node_Map* map ) {
tb_hash_map_exit( map->data );
MY_FREE( map );
}
Node_List* Node_List_Create() {
Node_List* node = ( Node_List* )MY_MALLOC( sizeof( Node_List ) );
node->type = TYPE_LIST;
node->data = tb_vector_init(
0,
tb_element_ptr( Node_free_, NULL )
);
return node;
}
#define Node_List_Destroy(x) do{ Node_List_Destroy_( ( Node_List* )x ); x = NULL; }while(0)
void
Node_List_Destroy_( Node_List* list ) {
tb_vector_exit( list->data );
MY_FREE( list );
}
Node_Scalar*
Node_Scalar_Create( const char* data, size_t len ) {
Node_Scalar* node = ( Node_Scalar* )MY_MALLOC( sizeof( Node_Scalar ) );
node->type = TYPE_SCALAR;
node->data = MY_MALLOC( sizeof( tb_string_t ) );
tb_string_init( ( tb_string_ref_t )node->data );
tb_string_cstrncat( ( tb_string_ref_t )node->data, data, len );
return node;
}
#define Node_Scalar_Destroy(x) do{ Node_Scalar_Destroy_( ( Node_Scalar*)x ); x = NULL; }while(0)
void
Node_Scalar_Destroy_( Node_Scalar* scalar ) {
tb_string_exit( scalar->data );
MY_FREE( scalar->data );
MY_FREE( scalar );
}
#define Node_free(x) do{ Node_free_(NULL, &x); x = NULL; }while(0)
tb_void_t
Node_free_( tb_element_ref_t element, tb_pointer_t buff ) {
Node* node = *( Node** )buff;
assert( node != NULL );
switch ( node->type ) {
case TYPE_MAP: {
Node_Map_Destroy( node );
break;
}
case TYPE_LIST: {
Node_List_Destroy( node );
break;
}
case TYPE_SCALAR: {
Node_Scalar_Destroy( node );
break;
}
}
}
void
Node_Append( Node* node, Node* data ) {
switch ( node->type ) {
case TYPE_MAP: {
#define Node_Map_TYPE(x) ( ( Node_Map* ) x )
if ( Node_Map_TYPE( node ) ->is_left == true ) {
Node_Map_TYPE( node )->pair = ( Node_Map_Pair* )MY_MALLOC(
sizeof( Node_Map_Pair )
);
Node_Map_TYPE( node )->pair->type = TYPE_MAP;
Node_Map_TYPE( node )->pair->left = data;
Node_Map_TYPE( node )->is_left = false;
} else {
Node_Map_TYPE( node )->pair->right = data;
tb_hash_map_insert( node->data,
( tb_pointer_t )( ( Node_Scalar* )( Node_Map_TYPE(
node )->pair->left ) )->data->data,
( tb_pointer_t )Node_Map_TYPE( node )->pair
);
Node_Map_TYPE( node )->pair = NULL;
Node_Map_TYPE( node )->is_left = true;
}
break;
#undef Node_Map_TYPE
}
case TYPE_LIST: {
#define Node_List_TYPE(x) ( ( Node_List* ) x )
tb_vector_insert_tail(
Node_List_TYPE( node )->data,
( tb_cpointer_t )data
);
break;
#undef Node_List_TYPE
}
default:
break;
}
}
Node*
Node_Get( Node* node, ... ) {
va_list valist;
va_start( valist, node );
for ( void* val = va_arg( valist, void* );
val != NULL;
val = va_arg( valist, void* )
) {
switch ( node->type ) {
case TYPE_MAP: {
tb_pointer_t p = tb_hash_map_get( ( ( Node_Map* )node )->data, val );
if ( p == NULL ) {
return NULL;
}
node = ( ( Node_Map_Pair* )p )->right;
break;
}
case TYPE_LIST: {
char* end = val;
intmax_t index = strtoimax( val, &end, 10 );
if (
end == val ||
index > tb_vector_size( ( ( Node_List* )node )->data )
) {
return NULL;
}
Node_List** list_data = tb_vector_data( ( ( Node_List* )node )->data );
node = ( Node* )list_data[index];
break;
}
case TYPE_SCALAR: {
return NULL;
break;
}
}
}
va_end( valist );
return node;
}
Node*
parser( const char* path ) {
yaml_parser_t parser;
yaml_event_t event;
assert( yaml_parser_initialize( &parser ) );
FILE* file = fopen( path, "rb" );
assert( file != NULL );
yaml_parser_set_input_file( &parser, file );
Node_Map* root = Node_Map_Create();
tb_stack_ref_t list = tb_stack_init( 10, tb_element_ptr( NULL, NULL ) );
bool quit = false;
while ( !quit ) {
if ( !yaml_parser_parse( &parser, &event ) ) {
perror( "解析失败" );
return NULL;
}
switch ( event.type ) {
case YAML_STREAM_END_EVENT: {
quit = true;
break;
}
case YAML_MAPPING_START_EVENT:
case YAML_SEQUENCE_START_EVENT: {
if ( tb_stack_size( list ) == 0 ) {
tb_stack_put( list, ( tb_cpointer_t )root );
break;
}
Node* node = NULL;
if ( event.type == YAML_MAPPING_START_EVENT ) {
node = ( Node* )Node_Map_Create();
} else {
node = ( Node* )Node_List_Create();
}
Node_Append( ( Node* )tb_stack_top( list ), ( Node* )node );
tb_stack_put( list, ( tb_cpointer_t )node );
break;
}
case YAML_MAPPING_END_EVENT:
case YAML_SEQUENCE_END_EVENT: {
tb_stack_pop( list );
break;
}
case YAML_SCALAR_EVENT: {
Node_Scalar* scalar = Node_Scalar_Create(
( char* )event.data.scalar.value,
event.data.scalar.length
);
// 这个是个 bug?
/* 注意这个冒号和值连在一起,这个竟然没有判断出错,也因此第三个事件是
* YAML_SCALAR_EVENT 而非 MAP
*
* key :value
* key2 : value2
*/
assert( tb_stack_size( list ) > 0 );
Node_Append( ( Node* )tb_stack_top( list ), ( Node* )scalar );
break;
}
default:
break;
}
}
yaml_event_delete( &event );
yaml_parser_delete( &parser );
fclose( file );
tb_stack_exit( list );
return ( Node* )root;
}
int
main( int argc, char* argv[] ) {
if ( !tb_init( tb_null, tb_native_allocator() ) ) return -1;
Node* root = parser( "data.yaml" );
Node* node = Node_Get( root, "list", "0", NULL );
if ( node == NULL ) {
printf( "没找到\n" );
} else {
if ( node->type == TYPE_SCALAR ) {
printf( "找到了:%.*s\n",
( ( Node_Scalar* )node )->data->size,
( ( Node_Scalar* )node )->data->data
);
} else {
printf( "类型是:%d\n", node->type );
}
}
Node_free( root );
return 0;
}
glib2
Raw Copy
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <assert.h>
#include <stdarg.h>
#include <yaml.h>
#include <glib.h>
#define MY_MALLOC malloc
#define MY_FREE free
typedef enum {
TYPE_NON,
TYPE_MAP,
TYPE_LIST,
TYPE_SCALAR
} TYPE;
typedef struct {
TYPE type;
void* data;
} Node;
typedef struct {
Node* left;
// Node* right;
} Node_Map_Pair;
typedef struct {
TYPE type;
GHashTable* data;
uint8_t is_left;
Node_Map_Pair pair;
} Node_Map;
typedef struct {
TYPE type;
GArray* data;
} Node_List;
typedef struct {
TYPE type;
GString* data;
} Node_Scalar;
void
Node_free_( gpointer data );
void
Node_free_g_array( gpointer data );
gboolean
Node_Map_Key_Equal( gconstpointer key1, gconstpointer key2 ) {
assert( ( ( Node* )key1 )->type == TYPE_SCALAR );
assert( ( ( Node* )key2 )->type == TYPE_SCALAR );
return g_string_equal( ( ( Node_Scalar* )key1 )->data,
( ( Node_Scalar* )key2 )->data
);
}
guint
Node_Map_Key_Hash( gconstpointer key ) {
assert( ( ( Node* )key )->type == TYPE_SCALAR );
return g_string_hash( ( ( Node_Scalar* )key )->data );
}
gboolean
Node_Map_Key_Find( gpointer key, gpointer value, gpointer user_data ) {
return g_string_equal( ( ( Node_Scalar* )key )->data, ( GString* )user_data );
}
Node_Map*
Node_Map_Create( ) {
Node_Map* node = ( Node_Map* )MY_MALLOC( sizeof( Node_Map ) );
node->type = TYPE_MAP;
node->data = g_hash_table_new_full( Node_Map_Key_Hash,
Node_Map_Key_Equal,
Node_free_,
Node_free_
);
node->is_left = true;
node->pair.left = NULL;
return node;
}
#define Node_Map_Destroy(x) { Node_Map_Destroy_( ( Node_Map* )x ); x = NULL; }
void
Node_Map_Destroy_( Node_Map* map ) {
g_hash_table_unref( map->data );
MY_FREE( map );
}
Node_List*
Node_List_Create() {
Node_List* node = ( Node_List* )MY_MALLOC( sizeof( Node_List ) );
node->type = TYPE_LIST;
node->data = g_array_new( FALSE, FALSE, sizeof( Node* ) );
g_array_set_clear_func( node->data, Node_free_g_array );
return node;
}
#define Node_List_Destroy(x) { Node_List_Destroy_( ( Node_List* )x ); x = NULL; }
void
Node_List_Destroy_( Node_List* list ) {
g_array_unref( list->data );
MY_FREE( list );
}
Node_Scalar*
Node_Scalar_Create( const char* data, size_t len ) {
Node_Scalar* node = ( Node_Scalar* )MY_MALLOC( sizeof( Node_Scalar ) );
node->type = TYPE_SCALAR;
node->data = g_string_new_len( data, len );
return node;
}
#define Node_Scalar_Destroy(x) { Node_Scalar_Destroy_( ( Node_Scalar*)x ); x = NULL; }
void
Node_Scalar_Destroy_( Node_Scalar* scalar ) {
g_string_free( scalar->data, TRUE );
MY_FREE( scalar );
}
void
Node_free_g_array( gpointer data ) {
Node_free_( ( gpointer ) * ( Node** )data );
}
#define Node_free(x) Node_free_(x); x = NULL
void
Node_free_( gpointer data ) {
Node* node = ( Node* )data;
assert( node != NULL );
switch ( node->type ) {
case TYPE_MAP: {
Node_Map_Destroy( node );
break;
}
case TYPE_LIST: {
Node_List_Destroy( node );
break;
}
case TYPE_SCALAR: {
Node_Scalar_Destroy( node );
break;
}
}
}
void
Node_Append( Node* node, Node* data ) {
switch ( node->type ) {
case TYPE_MAP: {
#define Node_Map_TYPE(x) ( ( Node_Map* ) x )
if ( Node_Map_TYPE( node ) ->is_left == true ) {
Node_Map_TYPE( node )->pair.left = data;
Node_Map_TYPE( node )->is_left = false;
} else {
// Node_Map_TYPE( node )->pair.right = data;
g_hash_table_insert( Node_Map_TYPE( node )->data,
Node_Map_TYPE( node )->pair.left,
data
);
Node_Map_TYPE( node )->is_left = true;
}
break;
#undef Node_Map_TYPE
}
case TYPE_LIST: {
#define Node_List_TYPE(x) ( ( Node_List* ) x )
g_array_append_val( Node_List_TYPE( node )->data, data );
break;
#undef Node_List_TYPE
}
}
}
Node*
Node_Get( Node* node, ... ) {
if ( node == NULL ) {
return NULL;
}
va_list valist;
va_start( valist, node );
GString* key = g_string_new( NULL );
for ( void* val = va_arg( valist, void* );
val != NULL;
val = va_arg( valist, void* )
) {
switch ( node->type ) {
case TYPE_MAP: {
g_string_overwrite( key, 0, val );
gpointer p = g_hash_table_find( ( ( Node_Map* )node )->data,
Node_Map_Key_Find,
key
);
if ( p == NULL ) {
return NULL;
}
node = p;
break;
}
case TYPE_LIST: {
char* end = val;
uintmax_t index = strtoumax( val, &end, 10 );
if (
end == val ||
index > ( ( Node_List* )node )->data->len
) {
return NULL;
}
Node* p = g_array_index( ( ( Node_List* )node )->data, Node*, index );
if ( p == NULL ) {
return NULL;
}
node = p;
break;
}
case TYPE_SCALAR: {
break;
}
}
}
g_string_free( key, TRUE );
va_end( valist );
return node;
}
Node*
parser( const char* path ) {
yaml_parser_t parser;
yaml_event_t event;
assert( yaml_parser_initialize( &parser ) );
FILE* file = fopen( path, "rb" );
assert( file != NULL );
yaml_parser_set_input_file( &parser, file );
Node_Map* root = Node_Map_Create();
#define GStack GQueue
#define g_stack_new g_queue_new
#define g_stack_free g_queue_free
#define g_stack_pop(x) g_queue_pop_tail(x)
#define g_stack_push(x, y) g_queue_push_tail(x, y)
#define g_stack_top(x) g_queue_peek_tail(x)
#define g_stack_size(x) g_queue_get_length(x)
GStack* list = g_stack_new();
bool quit = false;
while ( !quit ) {
if ( !yaml_parser_parse( &parser, &event ) ) {
perror( "解析失败" );
return NULL;
}
switch ( event.type ) {
case YAML_STREAM_END_EVENT: {
quit = true;
break;
}
case YAML_MAPPING_START_EVENT:
case YAML_SEQUENCE_START_EVENT: {
if ( g_stack_size( list ) == 0 ) {
g_stack_push( list, ( gpointer )root );
break;
}
Node* node = NULL;
if ( event.type == YAML_MAPPING_START_EVENT ) {
node = ( Node* )Node_Map_Create();
} else {
node = ( Node* )Node_List_Create();
}
Node_Append( ( Node* )g_stack_top( list ), ( Node* )node );
g_stack_push( list, ( gpointer )node );
break;
}
case YAML_MAPPING_END_EVENT:
case YAML_SEQUENCE_END_EVENT: {
g_stack_pop( list );
break;
}
case YAML_SCALAR_EVENT: {
Node_Scalar* scalar = Node_Scalar_Create(
( const char* )event.data.scalar.value,
event.data.scalar.length
);
// 这个是个 bug?
/* 注意这个冒号和值连在一起,这个竟然没有判断出错?也因此第三个事件是
* YAML_SCALAR_EVENT 而非 MAP
* key :value
* key2 : value2
*/
assert( g_stack_size( list ) > 0 );
Node_Append( ( Node* )g_stack_top( list ), ( Node* )scalar );
break;
}
default:
break;
}
}
yaml_event_delete( &event );
yaml_parser_delete( &parser );
fclose( file );
g_stack_free( list );
return ( Node* )root;
}
int
main( int argc, char* argv[] ) {
Node* root = parser( "data.yaml" );
Node_free( root );
Node* node = Node_Get( ( Node* )root, "list", "9", NULL );
if ( node == NULL ) {
printf( "没找到\n" );
} else {
if ( node->type == TYPE_SCALAR ) {
printf( "找到了:%.*s\n",
( ( Node_Scalar* )node )->data->len,
( ( Node_Scalar* )node )->data->str
);
} else {
printf( "类型是:%d\n", node->type );
}
}
return 0;
}

Comment list( 0 )

Sign in for post a comment

Help Search

191139_cd20d5fd_5186603 191143_ebef6f8d_5186603