#ifndef CS_TYPES_H #define CS_TYPES_H #if defined WIN32 || defined _WIN32 # define CS_CDECL __cdecl # define CS_STDCALL __stdcall #else # define CS_CDECL # define CS_STDCALL #endif #ifndef CS_EXTERN_C_FUNC_PTR # ifdef __cplusplus # define CS_EXTERN_C_FUNC_PTR(x) extern "C" { typedef x; } # else # define CS_EXTERN_C_FUNC_PTR(x) typedef x # endif #endif #ifndef CS_INLINE # if defined __cplusplus # define CS_INLINE inline # elif (defined WIN32 || defined _WIN32 || defined WINCE) && !defined __GNUC__ # define CS_INLINE __inline # else # define CS_INLINE static # endif #endif /* CS_INLINE */ #ifdef __cplusplus extern "C" { #endif #if (defined WIN32 || defined _WIN32 || defined WINCE) && defined CSAPI_EXPORTS # define CS_EXPORTS __declspec(dllexport) #else # define CS_EXPORTS #endif #ifndef CS_API # define CS_API(rettype) CS_EXPORTS rettype CS_CDECL #endif #ifdef __cplusplus } #endif //#define DEBUG_MODE #ifdef DEBUG_MODE static short debug_level = 3; #endif #endif /* CS_TYPES_H */
#ifndef SC_COMMON_H #define SC_COMMON_H #include "cs_types.h" #include <getopt.h> /*----------------------------------------------------------------------------*/ /** * @typedef opt_t * @brief struct option (@see man 3 getopt) */ typedef struct option opt_t; /*----------------------------------------------------------------------------*/ /** * @fn [CS_API] int is_digital ( * const char* __restrict param_value, * long long* __restrict param_digit, * int* param_base ); * @brief , . * * @a param_value * , long long. * @a param_base, * NULL * * @warning " " , * ( ). * * : * - <>[.e[+|-]<>]> * - [<><[h|H]> | [0x|0X]<>] * - <><[o|O]> * - <><[b|B]> * * @param param_value - * @param param_digit - * @param param_base - * @return : * 0, @a param_value - . * 1, @a param_value - . * -1, . * , -1, errno * : * EINVAL - ; * ERANGE - * ENOMEM - * EBADE - * */ CS_API(int) is_digital ( const char* __restrict param_value, long long* __restrict param_digit, int* param_base ); /*----------------------------------------------------------------------------*/ /** * @fn CS_API(char*) ltrim( const char* param_str ); * @brief . * * @param param_str - * @return NULL. * * - @a param_str, * "". * , NULL, errno * EINVAL ( ); */ CS_API(char*) ltrim( const char* param_str ); /*----------------------------------------------------------------------------*/ /** * @fn CS_API(char*) rtrim( const char* param_str ); * @brief . * * @param param_str - * @return (static pointer) NULL. * , NULL, errno * : * EINVAL - ; * ENOMEM - * EBADE - * * @warning - static pointer. ! */ CS_API(char*) rtrim( const char* param_str ); #ifdef __cplusplus } #endif #endif /* SC_COMMON_H */
#ifndef CONFIG_UTILS_H #define CONFIG_UTILS_H #include "../include/cs_types.h" /** * @typedef cfg_val_type_t * @brief */ typedef enum config_value_type { ptDigital = 0x01, /**< - */ ptString = 0x02 /**< - */ } cfg_val_type_t; /** * @typedef config_t * @brief */ typedef struct { char* name; /**< */ cfg_val_type_t type; /**< @a param_type*/ union { /**< */ char* str; /**< */ struct { long long digit; /**< */ int base; /**< */ }; }; } config_t; /** * @typedef txt_cfg_t * @brief . */ typedef struct txt_cfg { config_t value; struct txt_cfg* prev;/**< */ struct txt_cfg* next;/**< */ } txt_cfg_t; #ifdef __cplusplus extern "C" { #endif /*----------------------------------------------------------------------------*/ /** * @fn [CS_API] txt_cfg_t* config_Open (const char* __restrict param_filename); * @brief @a txt_cfg_t. * * @param param_file_name - * @return , * \a param_filename (NULL). * * NULL, errno * . * errno: * EINVAL - param_filename * ENOMEM - * ERANGE - . * EBADE - * * , * < > = < >. * : * * # server_broadcast = ANY ( ) * server_broadcast = ANY * * # * server_port = 8989 * * # * # : * # * # server_family = SOCKET_STREAM ( ) * server_family = SOCKET_STREAM * * #usb_vendor = 0x1111 * usb_vendor = 0xffff * usb_product = 0xaaaa * usb_ep_in = 0x01 * * @see config_Close */ CS_API(txt_cfg_t*) config_Open (const char* __restrict param_filename); /*----------------------------------------------------------------------------*/ /** * @fn [CS_API] void config_Close (txt_cfg_t** param_item); * @brief . * * @param param_item - @a txt_cfg_t * * @a param_item . * NULL. * * @see @a config_Open * @see @a free */ CS_API(void) config_Close (txt_cfg_t** param_item); #ifdef __cplusplus } #endif #endif /* CONFIG_UTILS_H */
cfg_val_type_t
to the enumeration, for example, ptBool
, by creating a parameter processing branch. Then you - lazier than I myself! #include "../include/cs_common.h" #include <stdlib.h> #include <errno.h> #include <limits.h> #include <string.h> #include <stdio.h> //#include <netdb.h> /*----------------------------------------------------------------------------*/ int is_digital ( const char* __restrict param_value, long long* __restrict param_digit, int* param_base ) { char* c_endptr; char* c_value; int i_base; int i_ret = 1; size_t u_len; errno = 0; if(param_value == NULL || param_digit == NULL) { errno = EINVAL; return (-1); } *param_digit = 0; errno = 0; /* */ switch(param_value[strlen(param_value)-1]) { case 'h' : case 'H' : i_base = 16; break; case 'o' : case 'O' : i_base = 8; break; case 'b' : case 'B' : i_base = 2; break; default : i_base = 10; } if(i_base == 10) { if(param_value[strlen(param_value)-1] < (int)'0' || param_value[strlen(param_value)-1] > (int)'9') { return (0); /**/ } } u_len = strlen(param_value); if(u_len > 1) { if((c_value = malloc(u_len+1)) == NULL) { /* , ! */ errno = ENOMEM; return (-1); } if((c_value = strncpy(c_value, param_value, u_len)) == NULL) { errno = EBADE; i_ret = -1; } else { /* 16- */ if(param_value[0] == '0') { switch(param_value[1]) { case 'X' : case 'x' : i_base = 16; break; default : ; } if(i_base == 16) { if((c_value = strncpy(c_value, param_value+2, u_len-2)) == NULL) { errno = EBADE; i_ret = -1; } else { if( strncpy(c_value+u_len-2, "h\0", 2) == NULL ) { errno = EBADE; i_ret = -1; } } } } } if(i_ret > -1) { /* - */ *param_digit = strtoll(c_value, &c_endptr, i_base); if(c_endptr == c_value) { /* */ i_ret = 0; } else { /* */ if( (errno == ERANGE && (*param_digit == LLONG_MIN || *param_digit == LLONG_MAX)) || (errno != 0 && *param_digit == 0) ) { /* */ i_ret = -1; } } } /* */ if(param_base != NULL) *param_base = i_base; /* */ free(c_value); } return(i_ret); } /*----------------------------------------------------------------------------*/ char* ltrim ( const char* param_str ) { size_t i; size_t u_length; if(param_str == NULL) { errno = EINVAL; return (NULL); } errno = 0; u_length = strlen(param_str); if(0 == u_length) return (""); for(i = 0; i < u_length; i++ ) if((int)(param_str[i]) != ' '/* */) /* , */ return ((char*)param_str+i); return (NULL); } /*----------------------------------------------------------------------------*/ char* rtrim( const char* param_str ) { size_t i; size_t u_length; char* ptr; /* !!! */ static /* !!! */ char* str; if(NULL == param_str) { errno = EINVAL; return (NULL); } u_length = strlen(param_str); if(u_length == 0) return (""); for(i = u_length, errno = 0; (0 == errno) && (i > 0); i--) { if((int)(param_str[i-1]) == ' ') continue; if(NULL != (ptr = malloc(i + 1))) { if(NULL != (str = strncpy(ptr, param_str, i))) { str[i] = '\0'; return(str); } else { free(ptr); errno = EBADE; } } else { errno = ENOMEM; } } return (NULL); }
#include "../include/cs_configfile.h" #include "../include/cs_common.h" #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <limits.h> #include <string.h> /*----------------------------------------------------------------------------*/ /**@internal * @fn void free_cfg_data (txt_cfg_t* param_result); * @brief @a txt_cfg_t. * * @param param_result - . */ void free_cfg_data (txt_cfg_t* param_result) { txt_cfg_t* p; errno = 0; for(p = param_result; p != NULL; p = p->next) { free(p->value.name); if(p->value.type == ptString) free(p->value.str); } if(param_result) free(param_result); } /*----------------------------------------------------------------------------*/ /**@internal * @fn int alloc_cfg_data ( * const char* __restrict param_name, * const char* __restrict param_value, * txt_cfg_t** __restrict param_result * ); * @brief param_result txt_cfg_t. * * @param param_name - * @param param_value - * @param param_result - * txt_params_t. * * @return 0 -1 . * , -1, * errno . * * @warning *param_result * , . * * . */ int alloc_cfg_data ( const char* __restrict param_name, const char* __restrict param_value, txt_cfg_t** __restrict param_result ) { size_t u_length_n, u_length_v; if(param_name == NULL || param_value == NULL || param_result == NULL) { errno = EINVAL; return(-1); } errno = 0; if((*param_result = malloc(sizeof(txt_cfg_t))) == NULL) return(-1); /* ""! * ( * free_param(...)) * , str NULL. * NULL, .. . * - free() */ if(memset (*param_result, 0, sizeof(txt_cfg_t)) == NULL) return(-1); u_length_n = strlen(param_name); if(u_length_n == 0) return(-1); (*param_result)->value.name = malloc(u_length_n+1); if((*param_result)->value.name == NULL) /* */ goto free; if(strncpy((*param_result)->value.name, param_name, u_length_n) != NULL) { /* */ switch( is_digital( param_value, &((*param_result)->value.digit), &((*param_result)->value.base) ) ) { case 0 : { /* */ u_length_v = strlen(param_value); if(u_length_v > 0) { /* */ (*param_result)->value.str = malloc(u_length_v+1); if((*param_result)->value.str == NULL) goto free; if(strncpy((*param_result)->value.str, param_value, u_length_v) == NULL) goto free; } (*param_result)->value.type = ptString; } break; case 1 : /* */ (*param_result)->value.type = ptDigital; break; default : { /* - */ errno = ERANGE; goto free; } } return (0); } free: free_cfg_data(*param_result); *param_result = NULL; return (-1); } /*----------------------------------------------------------------------------*/ /**@internal * * <> = <> * . * * @param param_str - [] = [] * @param param_name - * @param param_value - * @return 0 -1 . * * , -1, * errno . * * @warning *param_value / *param_name NULL, * . * . */ int parse_string ( const char* param_str, char** param_name, char** param_value ) { if(param_name == NULL || param_value == NULL) { errno = EINVAL; return -1; } *param_value = *param_name = NULL; if(param_str == NULL) { errno = EINVAL; return -1; } switch(param_str[0]) { case '\n' : case '#' : case 0 : return (0); } char c_name[MAX_INPUT]; char c_value[MAX_INPUT]; errno = 0; int i = sscanf(param_str, "%s = %s", c_name, c_value); char* p_name = ltrim(rtrim(c_name)); char* p_value = ltrim(rtrim(c_value)); if(errno != 0 || i != 2 ) return (-1); *param_name = malloc(strlen(p_name)+1); if(*param_name != NULL) { *param_value = malloc(strlen(p_value)+1); if(*param_value != NULL) { if(strcpy(*param_name, p_name) == NULL) { /* */ errno = EXFULL; goto freemem; } if(strcpy(*param_value, p_value) == NULL) { /* */ errno = EXFULL; goto freemem; } #ifdef DEBUG_MODE if(debug_level > 3) { printf("DEBUG parse_string(...). c_name = %s, c_value = %s, ", c_name, c_value); printf("*param_name = %s, *param_value = %s\n", *param_name, *param_value); } #endif return (0); } } freemem: if(*param_name != NULL) free(*param_name); if(*param_value != NULL) free(*param_value); *param_value = *param_name = NULL; return(-1); } /*----------------------------------------------------------------------------*/ /**@internal * * . * * @param param_file_name - * * @param param_result - * @return 0 * @a param_result. -1. * * @warning *param_result NULL, * . * . * * , * @a txt_params_t. * ( -1) * errno. *param_result * NULL ( ) * */ int parse_config_file ( const char* param_file_name, txt_cfg_t** param_result ) { if(param_result == NULL || param_result == NULL) { errno = EINVAL; return (-1); } char c_str[MAX_INPUT]; txt_cfg_t* t_param; char* c_name; char* c_value; errno = 0; FILE* p_fd = fopen(param_file_name, "r"); if(p_fd == NULL) /* */ return (-1); int i_res = 0; *param_result = NULL; errno = 0; /* */ while(fgets(c_str,MAX_INPUT,p_fd) != NULL && i_res == 0 ) { /* */ i_res = parse_string(c_str, &c_name, &c_value); if(i_res == 0) { if(c_name == NULL) /* (, ,...) */ continue; #ifdef DEBUG_MODE if(debug_level > 3) printf( "DEBUG parse_confif_file(...): source = \"%s\", name = %s, value = %s \n", c_str, c_name, c_value ); #endif if((i_res = alloc_cfg_data(c_name, c_value, &t_param)) == 0 ) { /* */ t_param->next = *param_result; if(*param_result != NULL) (*param_result)->prev = t_param; } /* i_res */ /* : ! */ free(c_name); free(c_value); *param_result = t_param; }/* i_res */ } if(i_res != 0) { free_cfg_data(*param_result); *param_result = NULL; } fclose(p_fd); return (i_res); } /*----------------------------------------------------------------------------*/ txt_cfg_t* config_Open (const char* param_filename) { txt_cfg_t* p_item = NULL; (void)parse_config_file(param_filename, &p_item); return (p_item); } /*----------------------------------------------------------------------------*/ void config_Close (txt_cfg_t** param_item) { if(param_item) { if(*param_item) { free_cfg_data(*param_item); *param_item = NULL; } } }
parse_string
function parse_string
try applying a regular expression parsing rule. So you get rid of the obligation to put spaces on both sides of the equal sign.ltrim
utilityrtrim
utilityis_digital
utility #------------------------------------------------------------------------------- # : # . #------------------------------------------------------------------------------- # #pid_file = ereusb.pid # # : bla, bla, bla... # # server_broadcast = ANY ( ) server_broadcast = ANY # server_port = 8989 # # : # # server_family = SOCKET_STREAM ( ) server_family = SOCKET_STREAM #usb_vendor = 0x1111 usb_vendor = 0001b usb_product = 1234o usb_ep_in = 0x01 usb_ep_out = 0x82
Source: https://habr.com/ru/post/148930/
All Articles