Simple coroutine library / objects in plain C Snapshot
|
00001 #include "val.h" 00002 #include <ctype.h> 00003 00004 static int parse_spec( const char **pos, VAL_TYPE *type) 00005 { 00006 const char *cur = *pos; 00007 int length = 0; 00008 00009 if (*cur == '\0') { 00010 return 1; 00011 } 00012 00013 for( ; isspace(*cur) ; ++cur); 00014 00015 if (*cur != '%') { 00016 return -1; 00017 } 00018 ++cur; 00019 00020 if (*cur == 's') { 00021 *type = VAL_TYPE_STRING; 00022 goto ret; 00023 } 00024 00025 if (*cur == 'p') { 00026 *type = VAL_TYPE_PTR; 00027 goto ret; 00028 } 00029 00030 for( length = 0; *cur == 'h'; ++cur,++length ); 00031 00032 if ( *cur == 'q') { 00033 ++cur; 00034 length = 4; 00035 } 00036 00037 if (*cur != 'd' && *cur != 'u') { 00038 return -1; 00039 } 00040 00041 switch( length ) { 00042 case 2: 00043 *type = *cur == 'd' ? VAL_TYPE_INT8 : VAL_TYPE_UINT8; 00044 goto ret; 00045 case 1: 00046 *type = *cur == 'd' ? VAL_TYPE_INT16 : VAL_TYPE_UINT16; 00047 goto ret; 00048 case 0: 00049 *type = *cur == 'd' ? VAL_TYPE_INT32 : VAL_TYPE_UINT32; 00050 goto ret; 00051 case 4: 00052 *type = *cur == 'd' ? VAL_TYPE_INT64 : VAL_TYPE_UINT64; 00053 goto ret; 00054 } 00055 return -1; 00056 00057 ret: 00058 *pos = cur + 1; 00059 return 0; 00060 } 00061 00062 int VALUES_printv( VALUES *values, const char *format, va_list ap ) 00063 { 00064 const char *pos; 00065 VAL_TYPE type; 00066 VAL val; 00067 int rt; 00068 ARRAY_reset( &values->values ); 00069 00070 pos = format; 00071 while( (rt = parse_spec( &pos, &type ) ) == 0 ) { 00072 val.type = type; 00073 switch( type ) { 00074 case VAL_TYPE_UINT8: 00075 val.u.u8 = (uint8_t) va_arg( ap, int32_t ); 00076 break; 00077 case VAL_TYPE_INT8: 00078 val.u.n8 = (int8_t) va_arg( ap, int32_t ); 00079 break; 00080 case VAL_TYPE_UINT16: 00081 val.u.u16 = (uint16_t) va_arg( ap, uint32_t ); 00082 break; 00083 case VAL_TYPE_INT16: 00084 val.u.n16 = (int16_t) va_arg( ap, int32_t ); 00085 break; 00086 case VAL_TYPE_UINT32: 00087 val.u.u32 = va_arg( ap, uint32_t ); 00088 break; 00089 case VAL_TYPE_INT32: 00090 val.u.n32 = va_arg( ap, int32_t ); 00091 break; 00092 case VAL_TYPE_UINT64: 00093 val.u.u64 = va_arg( ap, uint64_t ); 00094 break; 00095 case VAL_TYPE_INT64: 00096 val.u.n64 = va_arg( ap, int64_t ); 00097 break; 00098 case VAL_TYPE_STRING: 00099 case VAL_TYPE_PTR: 00100 val.u.pval = va_arg( ap, void * ); 00101 break; 00102 } 00103 ARRAY_push_back( &values->values, &val, sizeof(val) ); 00104 } 00105 va_end( ap ); 00106 00107 if (rt == -1) { 00108 return -1; 00109 } 00110 return 0; 00111 } 00112 00113 int VALUES_scanv( VALUES *values, const char *format, va_list ap ) 00114 { 00115 VAL_TYPE type; 00116 VAL *val; 00117 size_t i; 00118 const char *pos; 00119 void *ptr; 00120 int rt; 00121 00122 pos = format; 00123 for(i = 0; i < ARRAY_size(&values->values) && (rt = parse_spec( &pos, &type )) == 0; i++ ) { 00124 val = VALUES_at( values, i ); 00125 00126 if (val->type != type) { 00127 va_end(ap); 00128 return -1; 00129 } 00130 00131 ptr = va_arg( ap, void *); 00132 00133 switch( type ) { 00134 case VAL_TYPE_UINT8: 00135 * ((uint8_t *) ptr) = val->u.u8; 00136 break; 00137 case VAL_TYPE_INT8: 00138 * ((int8_t *) ptr) = val->u.n8; 00139 break; 00140 case VAL_TYPE_UINT16: 00141 * ((uint16_t *) ptr) = val->u.u16; 00142 break; 00143 case VAL_TYPE_INT16: 00144 * ((int16_t *) ptr) = val->u.n16; 00145 break; 00146 case VAL_TYPE_UINT32: 00147 * ((uint32_t *) ptr) = val->u.u32; 00148 break; 00149 case VAL_TYPE_INT32: 00150 * ((int32_t *) ptr) = val->u.n32; 00151 break; 00152 case VAL_TYPE_UINT64: 00153 * ((uint64_t *) ptr) = val->u.u64; 00154 break; 00155 case VAL_TYPE_INT64: 00156 * ((int64_t *) ptr) = val->u.n64; 00157 break; 00158 case VAL_TYPE_STRING: 00159 case VAL_TYPE_PTR: 00160 * ((char **) ptr) = val->u.sval; 00161 break; 00162 } 00163 } 00164 va_end( ap ); 00165 00166 if (rt == -1) { 00167 return -1; 00168 } 00169 if (*pos != '\0') { 00170 return -1; 00171 } 00172 return 0; 00173 } 00174 00175