|
funkalicious 0.1
|
00001 /* 00002 ** read_binary_data.c 00003 ** 00004 00005 Copyright (C) 2009 Joseph Pingenot 00006 00007 This program is free software: you can redistribute it and/or modify 00008 it under the terms of the GNU Affero General Public License as published by 00009 the Free Software Foundation, either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU Affero General Public License for more details. 00016 00017 You should have received a copy of the GNU Affero General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 00020 ** Made by (Johnny Q. Hacker) 00021 ** Login <solarion@borkborkbork> 00022 ** 00023 ** Started on Mon Nov 23 17:12:25 2009 Johnny Q. Hacker 00024 ** Last update Sun May 12 01:17:25 2002 Speed Blue 00025 */ 00026 00027 #include <stdlib.h> 00028 #include <glib-2.0/glib.h> 00029 #include <gio/gio.h> 00030 #include <stdio.h> 00031 #include "config.h" 00032 #include <libdotcode/binary_data_common.h> 00033 #include <libdotcode/dotcode_generic.h> 00034 #include "read_binary_data.h" 00035 #include "gcc_hints.h" 00036 00037 #define DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN 150 00038 00039 struct dotcode_data* dotcode_read_binary_data(GFile* file, GError **err) { 00040 return NULL; 00041 } 00042 00043 struct dotcode_vector* dotcode_read_vector(gboolean little_endian, enum dotcode_type t, GInputStream *is, GError **error) { 00044 struct dotcode_vector *vec = (struct dotcode_vector*)malloc(sizeof(struct dotcode_vector)); 00045 if(vec == NULL) { 00046 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 1, "dotcode::read_binary_data::read_vector: ERROR failed to allocate storage for a new vector."); 00047 return NULL; 00048 } 00049 vec->t = t; 00050 GError *e = NULL; 00051 size_t datum_size; 00052 /*Allocate the storage*/ 00053 switch(t) { 00054 case DOTCODE_FLOAT8: 00055 datum_size = sizeof(double); 00056 break; 00057 case DOTCODE_FLOAT4: 00058 datum_size = sizeof(float); 00059 break; 00060 case DOTCODE_INT: 00061 datum_size = sizeof(int); 00062 break; 00063 default: 00064 free(vec); 00065 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 3, "dotcode::read_binary_data::read_float: ERROR couldn't recognize type %d.", t); 00066 return NULL; 00067 } 00068 vec->data = malloc(3*datum_size); 00069 if(vec->data == NULL) { 00070 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 1, "dotcode::read_binary_data::read_vector: ERROR failed to allocate storage for the vector data."); 00071 free(vec); 00072 return NULL; 00073 } 00074 for(int i=0; i<3; i++) { 00075 switch(t) { 00076 case DOTCODE_FLOAT8: 00077 ((double*)(vec->data))[i] = dotcode_read_float8(little_endian, is, &e); 00078 break; 00079 case DOTCODE_FLOAT4: 00080 ((float*)(vec->data))[i] = dotcode_read_float4(little_endian, is, &e); 00081 break; 00082 case DOTCODE_INT: 00083 ((int*)(vec->data))[i] = dotcode_read_int(little_endian, is, &e); 00084 break; 00085 default: 00086 break; 00087 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 27, "dotcode::read_binary_data::read_vector: ERROR unkown dotcode type %d", t); 00088 } 00089 if(unlikely(e != NULL)) break; 00090 } 00091 if(unlikely(e != NULL)) { 00092 free(vec->data); 00093 free(vec); 00094 *error = e; 00095 return NULL; 00096 } 00097 return vec; 00098 } 00099 00100 struct dotcode_array* dotcode_read_array(gboolean little_endian, enum dotcode_type t, GInputStream *is, GError **error) { 00101 struct dotcode_array *arr = (struct dotcode_array*)malloc(sizeof(struct dotcode_array)); 00102 if(arr == NULL) { 00103 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 1, "dotcode::read_binary_data::read_array: ERROR failed to allocate storage for a new array."); 00104 return NULL; 00105 } 00106 arr->t = t; 00107 GError *e = NULL; 00108 arr->imin = dotcode_read_int(little_endian, is, &e); 00109 if(unlikely(e != NULL)) { 00110 free(arr); 00111 *error = e; 00112 return NULL; 00113 } 00114 arr->imax = dotcode_read_int(little_endian, is, &e); 00115 if(unlikely(e != NULL)) { 00116 free(arr); 00117 *error = e; 00118 return NULL; 00119 } 00120 /*Error checking: make sure min/max are sane.*/ 00121 if(arr->imin >= arr->imax) { 00122 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 1, "dotcode::read_binary_data::read_array: ERROR invalid min/max: imin=%d >= imax=%d.", arr->imin, arr->imax); 00123 free(arr); 00124 return NULL; 00125 } 00126 //fprintf(stderr, "read_array: Got new array: imin=%d imax=%d:\n", arr->imin, arr->imax); 00127 /*Allocate the storage*/ 00128 switch(t) { 00129 case DOTCODE_FLOAT8: 00130 arr->storage = malloc(sizeof(double)*(arr->imax-arr->imin + 1)); 00131 break; 00132 case DOTCODE_FLOAT4: 00133 arr->storage = malloc(sizeof(float)*(arr->imax-arr->imin + 1)); 00134 break; 00135 default: 00136 free(arr); 00137 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 3, "dotcode::read_binary_data::read_array_data: ERROR couldn't recognize type %d.", t); 00138 return NULL; 00139 } 00140 if(arr->storage == NULL) { 00141 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 1, "dotcode::read_binary_data::read_array: ERROR failed to allocate storage for the array data."); 00142 free(arr); 00143 return NULL; 00144 } 00145 for(int i=0; i<(arr->imax - arr->imin + 1); i++) { 00146 switch(t) { 00147 case DOTCODE_FLOAT8: 00148 ((double*)(arr->storage))[i] = dotcode_read_float8(little_endian, is, &e); 00149 //fprintf(stderr, "read_array: Got double value %d of %g\n", i, ((double*)(arr->storage))[i]); 00150 break; 00151 case DOTCODE_FLOAT4: 00152 ((float*)(arr->storage))[i] = dotcode_read_float4(little_endian, is, &e); 00153 //fprintf(stderr, "read_array: Got float value %d of %g\n", i, ((float*)(arr->storage))[i]); 00154 break; 00155 default: 00156 break; 00157 } 00158 if(unlikely(e != NULL)) { 00159 free(arr->storage); 00160 free(arr); 00161 *error = e; 00162 return NULL; 00163 } 00164 } 00165 return arr; 00166 } 00167 00168 char* dotcode_read_sstring(gboolean little_endian, GInputStream *is, GError **error) { 00169 GError *e = NULL; 00170 int N = dotcode_read_int(little_endian, is, &e); 00171 if(unlikely(e != NULL)) { 00172 *error = e; 00173 return NULL; 00174 } 00175 char *buffer = (char*)malloc(N+1); 00176 if(buffer == NULL) { 00177 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 1, "dotcode::read_binary_data::read_sstring: ERROR failed to allocate storage for a new sstring."); 00178 return NULL; 00179 } 00180 gsize size; 00181 e = NULL; 00182 if(!g_input_stream_read_all(is, buffer, N, &size, NULL, &e)) { 00183 *error = e; 00184 free(buffer); 00185 return NULL; 00186 } 00187 if(size != N) { 00188 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 1, "dotcode::read_binary_data::read_sstring: ERROR wanted %d bytes, but got %lu.", N, (long unsigned int)size); 00189 free(buffer); 00190 return NULL; 00191 } 00192 /*Ensure that we're NULL-terminated.*/ 00193 buffer[N] = '\0'; 00194 return buffer; 00195 } 00196 00197 int dotcode_read_int(gboolean little_endian, GInputStream *is, GError **error) { 00198 gsize size; 00199 union int_union_ { 00200 char buffer[DOTCODE_INT_SIZE]; 00201 int ival; 00202 } int_union; 00203 GError *e = NULL; 00204 if(!g_input_stream_read_all(is, int_union.buffer, DOTCODE_INT_SIZE, &size, NULL, &e)) { 00205 *error = e; 00206 return -1; 00207 } 00208 if(size != DOTCODE_INT_SIZE) { 00209 if(e != NULL) { 00210 g_propagate_prefixed_error(error, e, "dotcode::read_binary_data::read_int: ERROR wanted %d bytes, but got %lu.", DOTCODE_INT_SIZE, (long unsigned int)size); 00211 }else{ 00212 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 1, "dotcode::read_binary_data::read_int: ERROR wanted %d bytes, but got %lu.", DOTCODE_INT_SIZE, (long unsigned int)size); } 00213 return -1; 00214 } 00215 #ifdef WORDS_BIGENDIAN 00216 if(little_endian) 00217 #else 00218 if(!little_endian) 00219 #endif 00220 { 00221 /*Other endianness*/ 00222 flip_endian(int_union.buffer, DOTCODE_INT_SIZE); 00223 } 00224 return int_union.ival; 00225 } 00226 00227 double dotcode_read_float8(gboolean little_endian, GInputStream *is, GError **error) { 00228 gsize size; 00229 union float8_union_ { 00230 char buffer[DOTCODE_FLOAT8_SIZE]; 00231 double dval; 00232 } float8_union; 00233 GError *e = NULL; 00234 if(!g_input_stream_read_all(is, float8_union.buffer, DOTCODE_FLOAT8_SIZE, &size, NULL, &e)) { 00235 *error = e; 00236 return -1; 00237 } 00238 if(size != DOTCODE_FLOAT8_SIZE) { 00239 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 1, "dotcode::read_binary_data::read_int: ERROR wanted %d bytes, but got %lu.", DOTCODE_FLOAT8_SIZE, (long unsigned int)size); 00240 return -1; 00241 } 00242 #ifdef WORDS_BIGENDIAN 00243 if(little_endian) 00244 #else 00245 if(!little_endian) 00246 #endif 00247 { 00248 /*Other endianness*/ 00249 flip_endian(float8_union.buffer, DOTCODE_FLOAT8_SIZE); 00250 } 00251 return float8_union.dval; 00252 } 00253 00254 float dotcode_read_float4(gboolean little_endian, GInputStream *is, GError **error) { 00255 gsize size; 00256 union float4_union_ { 00257 char buffer[DOTCODE_FLOAT4_SIZE]; 00258 float fval; 00259 } float4_union; 00260 GError *e = NULL; 00261 if(!g_input_stream_read_all(is, float4_union.buffer, DOTCODE_FLOAT4_SIZE, &size, NULL, &e)) { 00262 *error = e; 00263 return -1; 00264 } 00265 if(size != DOTCODE_FLOAT4_SIZE) { 00266 *error = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 1, "dotcode::read_binary_data::read_int: ERROR wanted %d bytes, but got %lu.", DOTCODE_FLOAT4_SIZE, (long unsigned int)size); 00267 return -1; 00268 } 00269 #ifdef WORDS_BIGENDIAN 00270 if(little_endian) 00271 #else 00272 if(!little_endian) 00273 #endif 00274 { 00275 /*Other endianness*/ 00276 flip_endian(float4_union.buffer, DOTCODE_FLOAT4_SIZE); 00277 } 00278 return float4_union.fval; 00279 } 00280 00281 struct dotcode_tensor* dotcode_read_tensor(gboolean little_endian, GInputStream *is, GError **err) { 00282 struct dotcode_tensor* t = (struct dotcode_tensor*)malloc(sizeof(struct dotcode_tensor)); 00283 if(t == NULL) { 00284 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, DOTCODE_ERROR_MALLOCFAIL, "dotcode::read_binary_data::read_tensor: ERROR failed to allocate storage for a new stensor."); 00285 return NULL; 00286 } 00287 char* str; 00288 GError *e = NULL; 00289 str = dotcode_read_sstring(little_endian, is, &e); 00290 if((str == NULL) || (e != NULL)) { 00291 g_propagate_prefixed_error(err, e, "dotcode::read_binary_data::read_tensor: ERROR: failed to read tensor type information from input stream."); 00292 free(t); 00293 return NULL; 00294 } 00295 //fprintf(stderr, "Tensor=%s\n", str); 00296 /*This is all just to parse out what type we have. Ugh.*/ 00297 /*Rewrote to remove the annoying bit :)*/ 00298 GList *typelist = NULL; 00299 dotcode_determine_templated_type(str, &typelist, &e); 00300 if(e != NULL) { 00301 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data.c::dotcode_read_tensor: Failed to get type from type template string."); 00302 free(t); 00303 free(str); 00304 return NULL; 00305 } 00306 if((*(enum dotcode_type*)(typelist->data)) != DOTCODE_TENSOR) { 00307 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 159, "dotcode::read_binary_data::dotcode_read_tensor: ERROR: main type in templated type string (%s) was of type %s, not Tensor!", str, dotcode_string_from_type2(*(enum dotcode_type*)(typelist->data))); 00308 free(t); 00309 free(str); 00310 } 00311 if(typelist->next == NULL) { 00312 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 160, "dotcode::read_binary_data::dotcode_read_tensor: ERROR: Tensor type in templated type string (%s) was not given!", str); 00313 free(t); 00314 free(str); 00315 } 00316 free(str); 00317 t->t = (*(enum dotcode_type*)(typelist->next->data)); 00318 for(GList *l = typelist; l!=NULL; l=l->next) free(l->data); 00319 g_list_free(typelist); 00320 t->metadata = dotcode_read_sstring(little_endian, is, &e); 00321 if(unlikely(e != NULL)) { 00322 g_propagate_prefixed_error(err, e, "Failed to read tensor data type: first type of templated type (%s) was not a tensor! (it was %s)", str, dotcode_string_from_type2(*(enum dotcode_type*)(typelist->data))); 00323 free(t); 00324 return NULL; 00325 } 00326 //fprintf(stderr, "\tmetadata=(%s)\n", t->metadata); 00327 t->Nd = dotcode_read_int(little_endian, is, &e); 00328 if(unlikely(e != NULL)) { 00329 g_propagate_prefixed_error(err, e, "Failed to read in number of indices: "); 00330 free(t->metadata); 00331 free(t); 00332 return NULL; 00333 } 00334 t->indices = (int*)malloc(2*(t->Nd)*sizeof(int)); 00335 if(t->indices == NULL) { 00336 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 157, "dotcode::read_binary_data::read_tensor: ERROR: failed to allocate memory for tensor indices."); 00337 free(t->metadata); 00338 free(t); 00339 return NULL; 00340 } 00341 long int n_items = 1; 00342 for(int i=0; i<(t->Nd); i++) { 00343 //fprintf(stderr, "t->Nd=%d i=%d\n", t->Nd, i); 00344 (t->indices)[2*i] = dotcode_read_int(little_endian, is, &e); 00345 //fprintf(stderr, "t->Nd=%d i=%d index[%d]=%d\n", t->Nd, i, 2*i, (t->indices)[2*i]); 00346 if(unlikely(e != NULL)) { 00347 g_propagate_prefixed_error(err, e, "Failed to read in tensor minimum index %d: ", i); 00348 free(t->indices); 00349 free(t->metadata); 00350 free(t); 00351 return NULL; 00352 } 00353 (t->indices)[2*i+1] = dotcode_read_int(little_endian, is, &e); 00354 //fprintf(stderr, "t->Nd=%d i=%d index[%d]=%d\n", t->Nd, i, 2*i+1, (t->indices)[2*i+1]); 00355 if(unlikely(e != NULL)) { 00356 g_propagate_prefixed_error(err, e, "Failed to read in tensor maximum index %d: ", i); 00357 free(t->indices); 00358 free(t->metadata); 00359 free(t); 00360 return NULL; 00361 } 00362 //fprintf(stderr, "\t%d.min=%d\n", i, (t->indices)[2*i]); 00363 //fprintf(stderr, "\t%d.max=%d\n", i, (t->indices)[2*i+1]); 00364 n_items *= ((t->indices)[2*i+1] - (t->indices)[2*i] + 1); 00365 //fprintf(stderr, "\t%d.n_items=%ld\n", i, n_items); 00366 } 00367 size_t datum_size; 00368 switch(t->t) { 00369 case DOTCODE_FLOAT8: 00370 datum_size = sizeof(double); 00371 break; 00372 case DOTCODE_FLOAT4: 00373 datum_size = sizeof(float); 00374 break; 00375 case DOTCODE_INT: 00376 datum_size = sizeof(int); 00377 break; 00378 default: 00379 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 161, "dotcode::read_binary_data::read_tensor: (incident 1) ERROR: invalid tensor data type (%d)", t->t); 00380 free(t->indices); 00381 free(t->metadata); 00382 free(t); 00383 return NULL; 00384 } 00385 //fprintf(stderr, "Datum size for type %s: %ld times %ld data = %ld bytes\n", dotcode_string_from_type2(t->t), (long int) datum_size, n_items, n_items*datum_size); 00386 t->data = malloc(n_items*datum_size); 00387 if(t->data == NULL) { 00388 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 160, "dotcode::read_binary_data::read_tensor: ERROR: failed to allocate memory for tensor data."); 00389 free(t->indices); 00390 free(t->metadata); 00391 free(t); 00392 return NULL; 00393 } 00394 for(long int i=0; i<n_items; i++) { 00395 switch(t->t) { 00396 case DOTCODE_FLOAT8: 00397 ((double*)(t->data))[i] = dotcode_read_float8(little_endian, is, &e); 00398 //fprintf(stderr, "\tindex %ld=%g\n", i, ((double*)(t->data))[i]); 00399 break; 00400 case DOTCODE_FLOAT4: 00401 ((float*)(t->data))[i] = dotcode_read_float4(little_endian, is, &e); 00402 //fprintf(stderr, "\tindex %ld=%f\n", i, ((float*)(t->data))[i]); 00403 break; 00404 case DOTCODE_INT: 00405 ((int*)(t->data))[i] = dotcode_read_int(little_endian, is, &e); 00406 //fprintf(stderr, "\tindex %ld=%d\n", i, ((int*)(t->data))[i]); 00407 break; 00408 default: 00409 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 162, "dotcode::read_binary_data::read_tensor: (incident 2) ERROR: invalid tensor data type (%d)", t->t); 00410 free(t->indices); 00411 free(t->metadata); 00412 free(t); 00413 return NULL; 00414 } 00415 if(unlikely(e != NULL)) { 00416 g_propagate_prefixed_error(err, e, "Failed to read in %ld%s tensor datum: ", i, (i==1)?"st":(i==2)?"nd":(i==3)?"rd":"th"); 00417 free(t->indices); 00418 free(t->metadata); 00419 free(t); 00420 return NULL; 00421 } 00422 } 00423 return t; 00424 } 00425 00426 struct dotcode_gridspec { 00427 struct dotcode_array* gridsites[3]; 00428 int Ng_[3]; 00429 }; 00430 00431 /**Reads in a GridSpec. 00432 *\param little_endian: true if the file is in little_endian, false if 00433 *big. 00434 *\param is pointer to the GInputStream. 00435 *\param error pointer to an existing, initialized GError. 00436 *\note GridSpecs are internal to this file; they're not used anywhere 00437 * except in a Grid. 00438 */ 00439 struct dotcode_gridspec* dotcode_internal_read_gridspec(gboolean little_endian, GInputStream *is, GError **err) { 00440 GError *e = NULL; 00441 char* s; 00442 s = dotcode_read_sstring(little_endian, is, &e); 00443 if(unlikely(e != NULL)) { 00444 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data.c::dotcode_internal_read_gridspec: Error reading GridSpec sstring."); 00445 return NULL; 00446 } 00447 if(g_strcmp0(s, "GridSpec") != 0) { 00448 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 190, "libdotcode::read_binary_data::dotcode_internal_read_gridspec: Error: Data type string (%s) is invalid: not \"GridSpec\".", s); 00449 free(s); 00450 return NULL; 00451 } 00452 free(s); 00453 s = dotcode_read_sstring(little_endian, is, &e); 00454 if(unlikely(e != NULL)) { 00455 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data.c::dotcode_internal_read_gridspec: Error reading GridSpec version sstring."); 00456 return NULL; 00457 } 00458 if(g_strcmp0(s, "2.0") != 0) { 00459 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 190, "libdotcode::read_binary_data::dotcode_internal_read_gridspec: Error: Data type string (%s) is invalid: not \"2.0\".", s); 00460 free(s); 00461 return NULL; 00462 } 00463 free(s); 00464 struct dotcode_gridspec* gs = (struct dotcode_gridspec*)malloc(sizeof(struct dotcode_gridspec)); 00465 if(unlikely(gs == NULL)) { 00466 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, DOTCODE_ERROR_MALLOCFAIL, "libdotcode::read_binary_data::dotcode_internal_read_gridspec: Error: Failed to allocate storage for gridspec structure."); 00467 return NULL; 00468 } 00469 for(int i=0; i<3; i++) { 00470 gs->gridsites[i] = dotcode_read_array(little_endian, DOTCODE_FLOAT8, is, &e); 00471 //fprintf(stderr, "got gridsites[%d](m=%d M=%d)\n", i, gs->gridsites[i]->imin, gs->gridsites[i]->imax); 00472 if(unlikely(e != NULL)) { 00473 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data.c::dotcode_internal_read_gridspec: Error reading array<float8> %d.", i); 00474 free(gs); 00475 return NULL; 00476 } 00477 } 00478 for(int i=0; i<3; i++) { 00479 gs->Ng_[i] = dotcode_read_int(little_endian, is, &e); 00480 //fprintf(stderr, "got Ng[%d]\n", i); 00481 if(unlikely(e != NULL)) { 00482 GError *e2 = NULL; 00483 g_propagate_prefixed_error(&e2, e, "libdotcode::read_binary_data.c::dotcode_internal_read_gridspec: Error reading Ng_[%d].", i); 00484 e=NULL; 00485 dotcode_free_type(DOTCODE_ARRAY, gs->gridsites, 3, &e, FALSE); 00486 /*We could error in freeing the arrays; propagate error if this 00487 failed, else do a simple copy.*/ 00488 if(unlikely(e != NULL)) { 00489 g_propagate_prefixed_error(err, e2, "libdotcode::read_binary_data.c::dotcode_internal_read_gridspec: Failure while freeing structure after failing to get array<float8>[%d] (error message from free: %s)", i, e->message); 00490 g_error_free(e); 00491 }else{ 00492 *err = e2; 00493 } 00494 free(gs); 00495 return NULL; 00496 } 00497 } 00498 return gs; 00499 } 00500 00501 struct dotcode_grid* dotcode_read_grid(gboolean little_endian, GInputStream *is, GError **err) { 00502 GError *e = NULL; 00503 //fprintf(stderr, "dotcode_read_grid()\n"); 00504 struct dotcode_grid* g = (struct dotcode_grid*)malloc(sizeof(struct dotcode_grid)); 00505 if(g == NULL) { 00506 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, DOTCODE_ERROR_MALLOCFAIL, "dotcode::read_binary_data::read_grid: ERROR failed to allocate storage for a new sgrid."); 00507 return NULL; 00508 } 00509 //fprintf(stderr, "reading gridspec\n"); 00510 struct dotcode_gridspec* gs = dotcode_internal_read_gridspec(little_endian, is, &e); 00511 if(unlikely(e != NULL)) { 00512 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data.c::dotcode_read_gridspec: error getting GridSpec."); 00513 free(g); 00514 return NULL; 00515 } 00516 /*Copy over the data that are needed, then free the structure.*/ 00517 for(int i=0; i<3; i++) { 00518 g->Ng[i] = gs->Ng_[i]; 00519 g->gridsites[i] = gs->gridsites[i]; 00520 //fprintf(stderr, "copied Ng[%d], gridsites[%d]\n", i, i); 00521 } 00522 free(gs); 00523 g->data = dotcode_read_tensor(little_endian, is, &e); 00524 if(unlikely(e != NULL)) { 00525 GError *e2 = NULL; 00526 g_propagate_prefixed_error(&e2, e, "libdotcode::read_binary_data.c::dotcode_read_grid: Error reading tensor from input stream."); 00527 e=NULL; 00528 for(int i=0; i<3; i++) dotcode_free_type(DOTCODE_ARRAY, g->gridsites[i], 1, &e, TRUE); 00529 /*We could error in freeing the arrays; propagate error if this 00530 failed, else do a simple copy.*/ 00531 if(unlikely(e != NULL)) { 00532 g_propagate_prefixed_error(err, e2, "libdotcode::read_binary_data.c::dotcode_read_grid: Failure while freeing structure after failing to get tensor (error message from free: %s)", e->message); 00533 g_error_free(e); 00534 }else{ 00535 *err = e2; 00536 } 00537 free(g); 00538 return NULL; 00539 } 00540 return g; 00541 } 00542 00543 /**Call read_dotcode_typed_file if the data type header hasn't been 00544 written. 00545 */ 00546 void* read_dotcode_typed_file(enum dotcode_type t, GFile *infile, GError **err) { 00547 GError *e = NULL; 00548 GFileInputStream *fis = g_file_read(infile, NULL, &e); 00549 if(unlikely(e != NULL)) { 00550 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data::read_dotcode_typed_file: Error opening dotcode file for reading."); 00551 return NULL; 00552 } 00553 char c; 00554 gboolean little_endian; 00555 gsize b_read; 00556 g_input_stream_read_all((GInputStream*)fis, &c, 1, &b_read, NULL, &e); 00557 if(unlikely((e != NULL) || (b_read != 1))) { 00558 if(e == NULL) { 00559 e = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 172, "libdotcode::read_binary_data::read_dotcode_typed_file: Error reading endianness from file: read non-1 (more than or less than 1) bytes from file (read %ld bytes).", (long int)b_read); 00560 } 00561 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data::read_dotcode_typed_file: Error reading endianness from file."); 00562 return NULL; 00563 } 00564 switch(c) { 00565 case 'l': 00566 little_endian = TRUE; 00567 break; 00568 case 'b': 00569 little_endian = FALSE; 00570 break; 00571 default: 00572 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 170, "libdotcode::read_binary_data::read_dotcode_typed_file: libdotcode::read_dotcode_typed_file:: Invalid file endianness: %c (should be l or b)\n", c); 00573 return NULL; 00574 } 00575 void* val = dotcode_read_generic(t, little_endian, (GInputStream*)fis, &e); 00576 if(unlikely(e != NULL)) { 00577 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data::read_dotcode_typed_file: ERROR reading file type (%s) from file.", dotcode_string_from_type2(t)); 00578 return NULL; 00579 } 00580 g_input_stream_close((GInputStream*)fis, NULL, &e); 00581 if(unlikely(e != NULL)) { 00582 GError *e2; 00583 g_propagate_prefixed_error(&e2, e, "libdotcode::read_binary_data::read_dotcode_typed_file: ERROR closing file (with type %s).", dotcode_string_from_type2(t)); 00584 e = NULL; 00585 dotcode_free_type(t, val, 1, &e, TRUE); 00586 if(e != NULL) { 00587 g_propagate_prefixed_error(err, e2, "libdotcode::read_binary_data::read_dotcode_typed_file: ERROR freeing value (type %d/%s) after failing to close the input stream (free error was %s)", t, dotcode_string_from_type2(t), e->message); 00588 g_error_free(e); 00589 }else{ 00590 *err = e2; 00591 } 00592 return NULL; 00593 } 00594 g_object_unref(fis); 00595 return val; 00596 } 00597 00598 /**Call read_dotcode_generic_file if the data type header has been written. 00599 */ 00600 void* read_dotcode_generic_file(enum dotcode_type *t, GFile *infile, GError **err) { 00601 GError *e = NULL; 00602 GFileInputStream *fis = g_file_read(infile, NULL, &e); 00603 //fprintf(stderr, "read_dotcode_generic_file()\n"); 00604 if(unlikely(e != NULL)) { 00605 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data::read_dotcode_generic_file: Error opening dotcode file for reading."); 00606 return NULL; 00607 } 00608 char c; 00609 gboolean little_endian; 00610 gsize b_read; 00611 g_input_stream_read_all((GInputStream*)fis, &c, 1, &b_read, NULL, &e); 00612 if(unlikely((e != NULL) || (b_read != 1))) { 00613 if(e == NULL) { 00614 e = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 172, "libdotcode::read_binary_data::read_dotcode_generic_file: Error reading endianness from file: read non-1 (more than or less than 1) bytes from file (read %ld bytes).", (long int)b_read); 00615 } 00616 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data::read_dotcode_generic_file: Error reading endianness from file."); 00617 return NULL; 00618 } 00619 switch(c) { 00620 case 'l': 00621 little_endian = TRUE; 00622 break; 00623 case 'b': 00624 little_endian = FALSE; 00625 break; 00626 default: 00627 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 170, "libdotcode::read_binary_data::read_dotcode_generic_file: Invalid file endianness: %c (should be l or b)\n", c); 00628 return NULL; 00629 } 00630 //fprintf(stderr, "little_endian: %s\n", (little_endian)?"TRUE":"FALSE"); 00631 char* typestring = dotcode_read_sstring(little_endian, (GInputStream*)fis, &e); 00632 //fprintf(stderr, "got typestring: %s\n", typestring); 00633 if(e != NULL) { 00634 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data::read_dotcode_generic_file: ERROR getting type string from the dotcode file."); 00635 return NULL; 00636 } 00637 GList *tlist = NULL; 00638 dotcode_determine_templated_type(typestring, &tlist, &e); 00639 if(((*(enum dotcode_type*)(tlist->data)) == DOTCODE_INVALID_TYPE) 00640 || (tlist->next == NULL) 00641 || (e != NULL)) { 00642 char *str = NULL; 00643 if(e != NULL) { 00644 str = e->message; 00645 } 00646 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 175, "libdotcode::read_binary_data::read_dotcode_generic_file: Invalid dotcode data type header: %s. (error info from parser: %s)", typestring, str); 00647 free(typestring); 00648 for(GList *l = tlist; l!=NULL; l=l->next) free(l->data); 00649 g_list_free(tlist); 00650 if(e != NULL) g_error_free(e); 00651 return NULL; 00652 } 00653 *t = *(enum dotcode_type*)(tlist->data); 00654 switch(*t) { 00655 case DOTCODE_ARRAY: 00656 case DOTCODE_TENSOR: 00657 case DOTCODE_GRID: 00658 if((*(enum dotcode_type*)(tlist->next->data)) != DOTCODE_FLOAT8) { 00659 fprintf(stderr, "NOT DOTCODE_FLOAT8!!\n"); 00660 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 175, "libdotcode::read_binary_data::read_dotcode_generic_file: Invalid dotcode data type header: %s: templated subtype was not float8!)", typestring); 00661 free(typestring); 00662 for(GList *l = tlist; l!=NULL; l=l->next) free(l->data); 00663 g_list_free(tlist); 00664 return NULL; 00665 } 00666 default: 00667 break; 00668 } 00669 for(GList *l = tlist; l!=NULL; l=l->next) free(l->data); 00670 g_list_free(tlist); 00671 free(typestring); 00672 void* val = dotcode_read_generic(*t, little_endian, (GInputStream*)fis, &e); 00673 if(unlikely(e != NULL)) { 00674 g_propagate_prefixed_error(err, e, "libdotcode::read_binary_data::read_dotcode_generic_file: ERROR reading file type (%s) from file.", dotcode_string_from_type2(*t)); 00675 return NULL; 00676 } 00677 g_input_stream_close((GInputStream*)fis, NULL, &e); 00678 if(unlikely(e != NULL)) { 00679 GError *e2; 00680 g_propagate_prefixed_error(&e2, e, "libdotcode::read_binary_data::read_dotcode_generic_file: ERROR closing file (with type %s).", dotcode_string_from_type2(*t)); 00681 e = NULL; 00682 dotcode_free_type(*t, val, 1, &e, TRUE); 00683 if(e != NULL) { 00684 g_propagate_prefixed_error(err, e2, "libdotcode::read_binary_data::read_dotcode_generic_file: ERROR freeing value (type %d/%s) after failing to close the input stream (free error was %s)", *t, dotcode_string_from_type2(*t), e->message); 00685 g_error_free(e); 00686 }else{ 00687 *err = e2; 00688 } 00689 return NULL; 00690 } 00691 g_object_unref(fis); 00692 return val; 00693 } 00694 00695 00696 void* dotcode_read_generic(enum dotcode_type t, gboolean little_endian, GInputStream *is, GError **err) { 00697 double* i = NULL; 00698 float* j = NULL; 00699 int* k = NULL; 00700 switch(t) { 00701 case DOTCODE_FLOAT8: 00702 i = (double*)malloc(sizeof(double)); 00703 if(unlikely(i==NULL)) { 00704 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, DOTCODE_ERROR_MALLOCFAIL, "libdotcode::read_binary_data::dotcode_read_generic: ERROR: failed to allocate memory to hold a double."); 00705 return NULL; 00706 } 00707 *i = dotcode_read_float8(little_endian, is, err); 00708 return (void*)i; 00709 case DOTCODE_FLOAT4: 00710 j = (float*)malloc(sizeof(float)); 00711 if(unlikely(j==NULL)) { 00712 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, DOTCODE_ERROR_MALLOCFAIL, "libdotcode::read_binary_data::dotcode_read_generic: ERROR: failed to allocate memory to hold a float."); 00713 return NULL; 00714 } 00715 *j = dotcode_read_float4(little_endian, is, err); 00716 return (void*)j; 00717 case DOTCODE_INT: 00718 k = (int*)malloc(sizeof(int)); 00719 if(unlikely(k==NULL)) { 00720 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, DOTCODE_ERROR_MALLOCFAIL, "libdotcode::read_binary_data::dotcode_read_generic: ERROR: failed to allocate memory to hold an int."); 00721 return NULL; 00722 } 00723 *k = dotcode_read_int(little_endian, is, err); 00724 return (void*)k; 00725 case DOTCODE_VECTOR: 00726 return (void*)dotcode_read_vector(little_endian, t, is, err); 00727 case DOTCODE_ARRAY: 00728 return (void*)dotcode_read_array(little_endian, t, is, err); 00729 case DOTCODE_TENSOR: 00730 return (void*)dotcode_read_tensor(little_endian, is, err); 00731 case DOTCODE_GRID: 00732 return (void*)dotcode_read_grid(little_endian, is, err); 00733 default: 00734 *err = g_error_new(DOTCODE_READ_BINARY_DATA_GERROR_DOMAIN, 171, "libdotcode::read_binary_data::read_dotcode_read_generic: Can't recognize dotcode data type (%d/%s)", t, dotcode_string_from_type2(t)); 00735 return NULL; 00736 } 00737 return NULL; 00738 } 00739