| 1 | /* |
|---|
| 2 | This is a module which implements the notion of a dataset. Its is |
|---|
| 3 | designed for the use with scripting languages. |
|---|
| 4 | |
|---|
| 5 | copyright: GPL |
|---|
| 6 | |
|---|
| 7 | Mark Koennecke, October 2002 |
|---|
| 8 | */ |
|---|
| 9 | #include <stdlib.h> |
|---|
| 10 | #include <string.h> |
|---|
| 11 | #include "nxdataset.h" |
|---|
| 12 | |
|---|
| 13 | /*-----------------------------------------------------------------------*/ |
|---|
| 14 | static int getTypeSize(int typecode){ |
|---|
| 15 | switch(typecode){ |
|---|
| 16 | case NX_FLOAT32: |
|---|
| 17 | case NX_INT32: |
|---|
| 18 | case NX_UINT32: |
|---|
| 19 | return 4; |
|---|
| 20 | break; |
|---|
| 21 | case NX_FLOAT64: |
|---|
| 22 | case NX_INT64: |
|---|
| 23 | case NX_UINT64: |
|---|
| 24 | return 8; |
|---|
| 25 | break; |
|---|
| 26 | case NX_INT16: |
|---|
| 27 | case NX_UINT16: |
|---|
| 28 | return 2; |
|---|
| 29 | break; |
|---|
| 30 | default: |
|---|
| 31 | return 1; |
|---|
| 32 | break; |
|---|
| 33 | } |
|---|
| 34 | } |
|---|
| 35 | /*-----------------------------------------------------------------------*/ |
|---|
| 36 | pNXDS createNXDataset(int rank, int typecode, int64_t dim[]){ |
|---|
| 37 | pNXDS pNew = NULL; |
|---|
| 38 | int64_t length; |
|---|
| 39 | int i; |
|---|
| 40 | |
|---|
| 41 | pNew = (pNXDS)malloc(sizeof(NXDS)); |
|---|
| 42 | if(pNew == NULL){ |
|---|
| 43 | return NULL; |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | pNew->dim = (int64_t *)malloc(rank*sizeof(int64_t)); |
|---|
| 47 | for(i = 0, length = 1; i < rank; i++){ |
|---|
| 48 | length *= dim[i]; |
|---|
| 49 | } |
|---|
| 50 | /* add +1 in case of string NULL termination */ |
|---|
| 51 | pNew->u.ptr = malloc(length*getTypeSize(typecode)+1); |
|---|
| 52 | |
|---|
| 53 | if(pNew->dim == NULL || pNew->u.ptr == NULL){ |
|---|
| 54 | free(pNew); |
|---|
| 55 | return NULL; |
|---|
| 56 | } |
|---|
| 57 | pNew->rank = rank; |
|---|
| 58 | pNew->type = typecode; |
|---|
| 59 | pNew->format = NULL; |
|---|
| 60 | for(i = 0; i < rank; i++){ |
|---|
| 61 | pNew->dim[i] = dim[i]; |
|---|
| 62 | } |
|---|
| 63 | pNew->magic = MAGIC; |
|---|
| 64 | /* add +1 in case of string NULL termination - see above */ |
|---|
| 65 | memset(pNew->u.ptr,0,length*getTypeSize(typecode)+1); |
|---|
| 66 | return pNew; |
|---|
| 67 | } |
|---|
| 68 | /*---------------------------------------------------------------------*/ |
|---|
| 69 | pNXDS createTextNXDataset(char *name){ |
|---|
| 70 | pNXDS pNew = NULL; |
|---|
| 71 | |
|---|
| 72 | pNew = (pNXDS)malloc(sizeof(NXDS)); |
|---|
| 73 | if(pNew == NULL){ |
|---|
| 74 | return NULL; |
|---|
| 75 | } |
|---|
| 76 | pNew->dim = (int64_t *)malloc(sizeof(int64_t)); |
|---|
| 77 | pNew->u.cPtr = strdup(name); |
|---|
| 78 | if(pNew->dim == NULL || pNew->u.ptr == NULL){ |
|---|
| 79 | free(pNew); |
|---|
| 80 | return NULL; |
|---|
| 81 | } |
|---|
| 82 | pNew->rank = 1; |
|---|
| 83 | pNew->type = NX_CHAR; |
|---|
| 84 | pNew->magic = MAGIC; |
|---|
| 85 | pNew->dim[0] = strlen(name); |
|---|
| 86 | return pNew; |
|---|
| 87 | } |
|---|
| 88 | /*-----------------------------------------------------------------------*/ |
|---|
| 89 | void dropNXDataset(pNXDS dataset){ |
|---|
| 90 | if(dataset == NULL){ |
|---|
| 91 | return; |
|---|
| 92 | } |
|---|
| 93 | if(dataset->magic != MAGIC){ |
|---|
| 94 | return; |
|---|
| 95 | } |
|---|
| 96 | if(dataset->dim != NULL){ |
|---|
| 97 | free(dataset->dim); |
|---|
| 98 | } |
|---|
| 99 | if(dataset->u.ptr != NULL){ |
|---|
| 100 | free(dataset->u.ptr); |
|---|
| 101 | } |
|---|
| 102 | if(dataset->format != NULL){ |
|---|
| 103 | free(dataset->format); |
|---|
| 104 | } |
|---|
| 105 | free(dataset); |
|---|
| 106 | } |
|---|
| 107 | /*-----------------------------------------------------------------------*/ |
|---|
| 108 | int getNXDatasetRank(pNXDS dataset){ |
|---|
| 109 | if(dataset == NULL){ |
|---|
| 110 | return 0; |
|---|
| 111 | } |
|---|
| 112 | if(dataset->magic != MAGIC){ |
|---|
| 113 | return 0; |
|---|
| 114 | } |
|---|
| 115 | return dataset->rank; |
|---|
| 116 | } |
|---|
| 117 | /*-----------------------------------------------------------------------*/ |
|---|
| 118 | int getNXDatasetDim(pNXDS dataset, int which){ |
|---|
| 119 | if(dataset == NULL){ |
|---|
| 120 | return 0; |
|---|
| 121 | } |
|---|
| 122 | if(dataset->magic != MAGIC){ |
|---|
| 123 | return 0; |
|---|
| 124 | } |
|---|
| 125 | if(which < 0 || which >= dataset->rank){ |
|---|
| 126 | return 0; |
|---|
| 127 | } |
|---|
| 128 | return dataset->dim[which]; |
|---|
| 129 | } |
|---|
| 130 | /*------------------------------------------------------------------------*/ |
|---|
| 131 | int getNXDatasetType(pNXDS dataset){ |
|---|
| 132 | if(dataset == NULL){ |
|---|
| 133 | return 0; |
|---|
| 134 | } |
|---|
| 135 | if(dataset->magic != MAGIC){ |
|---|
| 136 | return 0; |
|---|
| 137 | } |
|---|
| 138 | return dataset->type; |
|---|
| 139 | } |
|---|
| 140 | /*--------------------------------------------------------------------*/ |
|---|
| 141 | int getNXDatasetLength(pNXDS dataset){ |
|---|
| 142 | int length, i; |
|---|
| 143 | |
|---|
| 144 | if(dataset == NULL){ |
|---|
| 145 | return 0; |
|---|
| 146 | } |
|---|
| 147 | if(dataset->magic != MAGIC){ |
|---|
| 148 | return 0; |
|---|
| 149 | } |
|---|
| 150 | length = dataset->dim[0]; |
|---|
| 151 | for(i = 1; i < dataset->rank; i++){ |
|---|
| 152 | length *= dataset->dim[i]; |
|---|
| 153 | } |
|---|
| 154 | return length; |
|---|
| 155 | } |
|---|
| 156 | /*---------------------------------------------------------------------*/ |
|---|
| 157 | int getNXDatasetByteLength(pNXDS dataset){ |
|---|
| 158 | return getNXDatasetLength(dataset)*getTypeSize(dataset->type); |
|---|
| 159 | } |
|---|
| 160 | /*---------------------------------------------------------------------- |
|---|
| 161 | This calculates an arbitray address in C storage order |
|---|
| 162 | -----------------------------------------------------------------------*/ |
|---|
| 163 | static int64_t calculateAddress(pNXDS dataset, int64_t pos[]){ |
|---|
| 164 | int64_t result, mult; |
|---|
| 165 | int i, j; |
|---|
| 166 | |
|---|
| 167 | result = pos[dataset->rank - 1]; |
|---|
| 168 | for(i = 0; i < dataset->rank -1; i++){ |
|---|
| 169 | mult = 1; |
|---|
| 170 | for(j = dataset->rank -1; j > i; j--){ |
|---|
| 171 | mult *= dataset->dim[j]; |
|---|
| 172 | } |
|---|
| 173 | if(pos[i] < dataset->dim[i] && pos[i] > 0){ |
|---|
| 174 | result += mult*pos[i]; |
|---|
| 175 | } |
|---|
| 176 | } |
|---|
| 177 | return result; |
|---|
| 178 | } |
|---|
| 179 | /*-----------------------------------------------------------------------*/ |
|---|
| 180 | double getNXDatasetValue(pNXDS dataset, int64_t pos[]){ |
|---|
| 181 | int64_t address; |
|---|
| 182 | |
|---|
| 183 | if(dataset == NULL){ |
|---|
| 184 | return 0; |
|---|
| 185 | } |
|---|
| 186 | if(dataset->magic != MAGIC){ |
|---|
| 187 | return 0; |
|---|
| 188 | } |
|---|
| 189 | |
|---|
| 190 | address = calculateAddress(dataset,pos); |
|---|
| 191 | return getNXDatasetValueAt(dataset, address); |
|---|
| 192 | } |
|---|
| 193 | /*----------------------------------------------------------------------*/ |
|---|
| 194 | double getNXDatasetValueAt(pNXDS dataset, int64_t address){ |
|---|
| 195 | double value; |
|---|
| 196 | |
|---|
| 197 | if(dataset == NULL){ |
|---|
| 198 | return 0; |
|---|
| 199 | } |
|---|
| 200 | if(dataset->magic != MAGIC){ |
|---|
| 201 | return 0; |
|---|
| 202 | } |
|---|
| 203 | |
|---|
| 204 | switch(dataset->type){ |
|---|
| 205 | case NX_FLOAT64: |
|---|
| 206 | value = dataset->u.dPtr[address]; |
|---|
| 207 | break; |
|---|
| 208 | case NX_FLOAT32: |
|---|
| 209 | value = (double)dataset->u.fPtr[address]; |
|---|
| 210 | break; |
|---|
| 211 | case NX_INT32: |
|---|
| 212 | case NX_UINT32: |
|---|
| 213 | value = (double)dataset->u.iPtr[address]; |
|---|
| 214 | break; |
|---|
| 215 | case NX_INT64: |
|---|
| 216 | case NX_UINT64: |
|---|
| 217 | value = (double)dataset->u.lPtr[address]; |
|---|
| 218 | break; |
|---|
| 219 | case NX_INT16: |
|---|
| 220 | case NX_UINT16: |
|---|
| 221 | value = (double)dataset->u.sPtr[address]; |
|---|
| 222 | break; |
|---|
| 223 | default: |
|---|
| 224 | value = (double)dataset->u.cPtr[address]; |
|---|
| 225 | break; |
|---|
| 226 | } |
|---|
| 227 | return value; |
|---|
| 228 | } |
|---|
| 229 | /*-----------------------------------------------------------------------*/ |
|---|
| 230 | char *getNXDatasetText(pNXDS dataset){ |
|---|
| 231 | char *resultBuffer = NULL; |
|---|
| 232 | int status = 1; |
|---|
| 233 | |
|---|
| 234 | if(dataset == NULL){ |
|---|
| 235 | return strdup("NULL"); |
|---|
| 236 | } |
|---|
| 237 | if(dataset->magic != MAGIC){ |
|---|
| 238 | return strdup("NULL"); |
|---|
| 239 | } |
|---|
| 240 | if(dataset->rank > 1){ |
|---|
| 241 | status = 0; |
|---|
| 242 | } |
|---|
| 243 | if(dataset->type == NX_FLOAT32 || |
|---|
| 244 | dataset->type == NX_FLOAT64 || |
|---|
| 245 | dataset->type == NX_INT32 || |
|---|
| 246 | dataset->type == NX_UINT32 || |
|---|
| 247 | dataset->type == NX_INT64 || |
|---|
| 248 | dataset->type == NX_UINT64 || |
|---|
| 249 | dataset->type == NX_INT16 || |
|---|
| 250 | dataset->type == NX_UINT16 ) { |
|---|
| 251 | status = 0; |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | if(status == 0){ |
|---|
| 255 | return strdup("NO type problem"); |
|---|
| 256 | }else{ |
|---|
| 257 | resultBuffer = (char *)malloc((dataset->dim[0]+10)*sizeof(char)); |
|---|
| 258 | if(resultBuffer == NULL){ |
|---|
| 259 | return strdup("NO Memory"); |
|---|
| 260 | } |
|---|
| 261 | memset(resultBuffer,0,(dataset->dim[0]+10)*sizeof(char)); |
|---|
| 262 | strncpy(resultBuffer,dataset->u.cPtr,dataset->dim[0]); |
|---|
| 263 | } |
|---|
| 264 | return resultBuffer; |
|---|
| 265 | } |
|---|
| 266 | /*----------------------------------------------------------------------*/ |
|---|
| 267 | int putNXDatasetValue(pNXDS dataset, int64_t pos[], double value){ |
|---|
| 268 | int64_t address; |
|---|
| 269 | |
|---|
| 270 | if(dataset == NULL){ |
|---|
| 271 | return 0; |
|---|
| 272 | } |
|---|
| 273 | if(dataset->magic != MAGIC){ |
|---|
| 274 | return 0; |
|---|
| 275 | } |
|---|
| 276 | |
|---|
| 277 | address = calculateAddress(dataset,pos); |
|---|
| 278 | return putNXDatasetValueAt(dataset,address,value); |
|---|
| 279 | } |
|---|
| 280 | /*---------------------------------------------------------------------*/ |
|---|
| 281 | int putNXDatasetValueAt(pNXDS dataset, int64_t address, double value){ |
|---|
| 282 | /* |
|---|
| 283 | this code is dangerous, it casts without checking the data range. |
|---|
| 284 | This may cause trouble in some cases |
|---|
| 285 | */ |
|---|
| 286 | switch(dataset->type){ |
|---|
| 287 | case NX_FLOAT64: |
|---|
| 288 | dataset->u.dPtr[address] = value; |
|---|
| 289 | break; |
|---|
| 290 | case NX_FLOAT32: |
|---|
| 291 | dataset->u.fPtr[address] = (float)value; |
|---|
| 292 | break; |
|---|
| 293 | case NX_INT32: |
|---|
| 294 | case NX_UINT32: |
|---|
| 295 | dataset->u.iPtr[address] = (int)value; |
|---|
| 296 | break; |
|---|
| 297 | case NX_INT64: |
|---|
| 298 | case NX_UINT64: |
|---|
| 299 | dataset->u.lPtr[address] = (int64_t)value; |
|---|
| 300 | break; |
|---|
| 301 | case NX_INT16: |
|---|
| 302 | case NX_UINT16: |
|---|
| 303 | dataset->u.sPtr[address] = (short int)value; |
|---|
| 304 | break; |
|---|
| 305 | default: |
|---|
| 306 | dataset->u.cPtr[address] = (char)value; |
|---|
| 307 | break; |
|---|
| 308 | } |
|---|
| 309 | return 1; |
|---|
| 310 | } |
|---|
| 311 | |
|---|
| 312 | |
|---|
| 313 | |
|---|