00001 00005 #include <malloc.h> 00006 #include <string.h> 00007 00008 #include "libmgk.h" 00009 #include "allocate.h" 00010 00011 DEFINE_ALLOCATOR(mgk_value, 500, next); 00012 00013 #define TYPE_MASK ((2 * T_ARRAY(0)) - 1) 00014 #define SCALAR_MASK (T_BUFFER - 1) 00015 #define TYPE_SIZE(t) ((unsigned int)(t) >> 8) 00016 00017 #define T_ALIAS ((unsigned int)(-2)) 00018 00019 mgk_value * 00020 __mgk_build_value(void *data, mgk_data_type type) 00021 { 00022 int itemsize, count; 00023 mgk_value *vp; 00024 mgk_buffer *bp; 00025 if (!data) { 00026 mgk_errno = E_BADDATA; 00027 return (NULL); 00028 } 00029 if (!(vp = ALLOC_mgk_value())) { 00030 mgk_errno = E_NOMEM; 00031 return (NULL); 00032 } 00033 vp->create_time = __mgk_tick; 00034 vp->next = NULL; 00035 vp->value = &vp->scalar_val; 00036 switch (type & TYPE_MASK) { 00037 case T_CHAR: 00038 vp->type = T_CHAR; 00039 vp->scalar_val.C = *((char *)(data)); 00040 return (vp); 00041 case T_SHORTINT: 00042 vp->type = T_SHORTINT; 00043 vp->scalar_val.S = *((short *)(data)); 00044 return (vp); 00045 case T_INTEGER: 00046 vp->type = T_INTEGER; 00047 vp->scalar_val.I = *((int *)(data)); 00048 return (vp); 00049 case T_LONGINT: 00050 vp->type = T_LONGINT; 00051 vp->scalar_val.L = *((long *)(data)); 00052 return (vp); 00053 case T_FLOAT: 00054 vp->type = T_FLOAT; 00055 vp->scalar_val.F = *((float *)(data)); 00056 return (vp); 00057 case T_DOUBLE: 00058 vp->type = T_DOUBLE; 00059 vp->scalar_val.D = *((double *)(data)); 00060 return (vp); 00061 case T_BUFFER | T_UNKNOWN: 00062 case T_BUFFER | T_CHAR: 00063 case T_BUFFER | T_SHORTINT: 00064 case T_BUFFER | T_INTEGER: 00065 case T_BUFFER | T_LONGINT: 00066 case T_BUFFER | T_FLOAT: 00067 case T_BUFFER | T_DOUBLE: 00068 if ((bp = __mgk_checked_buffer_header(data))) { 00069 vp->type = type & TYPE_MASK; 00070 if (bp->refval) { 00071 void *dtacopy = __mgk_copy_buffer(data); 00072 if (!dtacopy) { 00073 FREE_mgk_value(vp); 00074 return (NULL); 00075 } 00076 vp->value = dtacopy; 00077 bp = __mgk_buffer_header(dtacopy); 00078 } 00079 else { 00080 vp->value = data; 00081 } 00082 bp->refval = vp; 00083 return (vp); 00084 } 00085 break; 00086 case T_ARRAY(0) | T_CHAR: 00087 itemsize = sizeof(char); 00088 if (type == T_STRING) { 00089 count = strlen((char *)data) + 1; 00090 goto array2; 00091 } 00092 goto array1; 00093 case T_ARRAY(0) | T_SHORTINT: 00094 itemsize = sizeof(short); 00095 goto array1; 00096 case T_ARRAY(0) | T_INTEGER: 00097 itemsize = sizeof(int); 00098 goto array1; 00099 case T_ARRAY(0) | T_LONGINT: 00100 itemsize = sizeof(long); 00101 goto array1; 00102 case T_ARRAY(0) | T_FLOAT: 00103 itemsize = sizeof(float); 00104 goto array1; 00105 case T_ARRAY(0) | T_DOUBLE: 00106 itemsize = sizeof(double); 00107 array1: 00108 count = ((unsigned int)(type)) >> 8; 00109 array2: 00110 if ((itemsize * count) > 0) { 00111 void *dtacopy = __mgk_allocate_buffer(itemsize * count); 00112 if (dtacopy) { 00113 bp = __mgk_buffer_header(dtacopy); 00114 memcpy(dtacopy, data, (itemsize * count)); 00115 vp->value = dtacopy; 00116 vp->type = (type & SCALAR_MASK) | T_BUFFER; 00117 bp->refval = vp; 00118 return (vp); 00119 } 00120 } 00121 break; 00122 default: 00123 break; 00124 } 00125 FREE_mgk_value(vp); 00126 mgk_errno = E_BADDATA; 00127 return (NULL); 00128 } 00129 00130 void * 00131 __mgk_parse_value(mgk_value * vp, mgk_data_type * typep) 00132 { 00133 if (vp && (vp->type == T_ALIAS)) { 00134 vp = vp->value; 00135 } 00136 if (vp) { 00137 *typep = vp->type; 00138 return (vp->value); 00139 } 00140 *typep = T_NODATA; 00141 return (NULL); 00142 } 00143 00144 mgk_value * 00145 __mgk_copy_value(mgk_value * vp) 00146 { 00147 mgk_data_type type; 00148 void *data = __mgk_parse_value(vp, &type); 00149 return (data ? __mgk_build_value(data, type) : NULL); 00150 } 00151 00152 mgk_value * 00153 __mgk_alias_value(mgk_value * vp) 00154 { 00155 mgk_value *valias; 00156 if (vp && (vp->type == T_ALIAS)) { 00157 vp = vp->value; 00158 } 00159 if (vp && ((valias = ALLOC_mgk_value()))) { 00160 valias->create_time = vp->create_time; 00161 valias->next = NULL; 00162 if (!(vp->type & T_BUFFER)) { 00163 valias->type = vp->type; 00164 valias->scalar_val = vp->scalar_val; 00165 valias->value = &valias->scalar_val; 00166 } 00167 else { 00168 valias->type = T_ALIAS; 00169 valias->value = vp; 00170 vp->scalar_val.I = (-1); 00171 } 00172 return (valias); 00173 } 00174 return (NULL); 00175 } 00176 00177 mgk_value * 00178 __mgk_alias_value_autofree(mgk_value * vp, int *refcnt) 00179 { 00180 mgk_value *valias; 00181 if (vp && (vp->type == T_ALIAS)) { 00182 vp = vp->value; 00183 } 00184 if (vp && ((valias = ALLOC_mgk_value()))) { 00185 valias->create_time = vp->create_time; 00186 valias->next = NULL; 00187 if (!(vp->type & T_BUFFER)) { 00188 valias->type = vp->type; 00189 valias->scalar_val = vp->scalar_val; 00190 valias->value = &valias->scalar_val; 00191 } 00192 else { 00193 valias->type = T_ALIAS; 00194 valias->value = vp; 00195 vp->scalar_val.I = ++(*refcnt); 00196 } 00197 return (valias); 00198 } 00199 return (NULL); 00200 } 00201 00202 void * 00203 __mgk_extract_value(mgk_value * vp, mgk_data_type * tp, mgk_scalar * s) 00204 { 00205 int do_destroy = TRUE; 00206 if (vp && (vp->type == T_ALIAS)) { 00207 mgk_value *aliased = vp->value; 00208 FREE_mgk_value(vp); 00209 vp = aliased; 00210 if (vp) { 00211 if (vp->scalar_val.I < 0) { 00212 do_destroy = FALSE; 00213 } 00214 else { 00215 vp->scalar_val.I--; 00216 if (vp->scalar_val.I > 0) { 00217 do_destroy = FALSE; 00218 } 00219 } 00220 } 00221 } 00222 if (!vp) { 00223 *tp = T_NODATA; 00224 return (NULL); 00225 } 00226 *tp = vp->type; 00227 if (!do_destroy) { 00228 return (vp->value); 00229 } 00230 if (vp->type & T_BUFFER) { 00231 void *val = vp->value; 00232 mgk_buffer *bp = __mgk_checked_buffer_header(val); 00233 if (bp && (bp->refval == vp)) { 00234 bp->refval = NULL; 00235 } 00236 FREE_mgk_value(vp); 00237 return (val); 00238 } 00239 *s = vp->scalar_val; 00240 FREE_mgk_value(vp); 00241 return (s); 00242 } 00243 00244 void 00245 __mgk_free_value(mgk_value * vp) 00246 { 00247 if (vp && (vp->type == T_ALIAS)) { 00248 mgk_value *aliased = vp->value; 00249 FREE_mgk_value(vp); 00250 if ((vp = aliased)) { 00251 if (vp->scalar_val.I < 0) { 00252 return; 00253 } 00254 vp->scalar_val.I--; 00255 if (vp->scalar_val.I > 0) { 00256 return; 00257 } 00258 } 00259 } 00260 if (vp) { 00261 if (vp->type & T_BUFFER) { 00262 mgk_buffer *bp = __mgk_checked_buffer_header(vp->value); 00263 if (bp && (bp->refval == vp)) { 00264 bp->refval = NULL; 00265 __mgk_free_buffer(vp->value); 00266 } 00267 } 00268 FREE_mgk_value(vp); 00269 } 00270 } 00271 00272 void 00273 __mgk_free_value_list(mgk_value * vp) 00274 { 00275 while (vp) { 00276 mgk_value *next = vp->next; 00277 __mgk_free_value(vp); 00278 vp = next; 00279 } 00280 }