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 }