funkalicious 0.1

read_binary_data.c

Go to the documentation of this file.
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 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines