funkalicious 0.1

write_binary_data.c

Go to the documentation of this file.
00001 /*
00002 ** write_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@nathan>
00022 ** 
00023 ** Started on  Tue Nov 24 21:38:34 2009 Johnny Q. Hacker
00024 ** Last update Sun May 12 01:17:25 2002 Speed Blue
00025 */
00026 
00027 #include <string.h>
00028 #include <glib-2.0/glib.h>
00029 #include <gio/gio.h>
00030 #include "config.h"
00031 #include <libdotcode/dotcode_generic.h>
00032 #include <libdotcode/binary_data_common.h>
00033 #include "write_binary_data.h"
00034 #include "gcc_hints.h"
00035 
00036 #define DOTCODE_WRITE_BINARY_DATA_GERROR_DOMAIN 7032
00037 
00038 GError* dotcode_write_binary_data(const struct dotcode_data* data, GFile* file) {
00039   return NULL;
00040 }
00041 
00042 
00043 GError* dotcode_write_typed_file(const enum dotcode_type t, const void* data, GFile *outfile) {
00044   GError *e = NULL;
00045   GError *err = NULL;
00046   char* str;
00047   GFileIOStream *gfios = g_file_replace_readwrite(outfile, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &e);
00048   if(unlikely(e != NULL)) {
00049     g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_dotcode_typed_file: Error opening dotcode file (%s) for writing a %d(%s).", str=g_file_get_uri(outfile), t, dotcode_string_from_type2(t));
00050     g_free(str);
00051     return err;
00052   }
00053   GOutputStream *os = g_io_stream_get_output_stream((GIOStream*)gfios);
00054   char b;
00055   #ifdef WORDS_BIGENDIAN
00056   b = 'b';
00057   #else
00058   b = 'l';
00059   #endif
00060   gsize s;
00061   g_output_stream_write_all(os, &b, 1, &s, NULL, &e);
00062   if((e != NULL) || (s != 1)) {
00063     if(e != NULL) {
00064       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_dotcode_typed_file: Error writing endianness (%c) to output file (%s).", b, g_file_get_uri(outfile));
00065     }else{
00066       err = g_error_new(DOTCODE_WRITE_BINARY_DATA_GERROR_DOMAIN, 180, "libdotcode::write_binary_data::write_dotcode_typed_file: Error writing endianness (%c) to output file (%s): more or less than 1 byte written (%ld bytes were written)", b, g_file_get_uri(outfile), (long int)s);
00067     }
00068     return err;
00069   }
00070   err = dotcode_write_generic(t, data, TRUE, os);
00071   g_object_unref(gfios);
00072   return err;
00073 }
00074 
00075 
00076 GError* dotcode_write_generic(const enum dotcode_type t, const void* data, gboolean write_header, GOutputStream *os) {
00077   GError *err = NULL;
00078   switch(t) {
00079   case DOTCODE_FLOAT8:
00080     err = dotcode_write_float8(*((double*)data), write_header, os);
00081     break;
00082   case DOTCODE_FLOAT4:
00083     err = dotcode_write_float4((*(float*)data), write_header, os);
00084     break;
00085   case DOTCODE_INT:
00086     err = dotcode_write_int(*((int*)data), write_header, os);
00087     break;
00088   case DOTCODE_VECTOR:
00089     err = dotcode_write_vector((struct dotcode_vector*)data, write_header, os);
00090     break;
00091   case DOTCODE_ARRAY:
00092     err = dotcode_write_array((struct dotcode_array*)data, write_header, os);
00093     break;
00094   case DOTCODE_TENSOR:
00095     err = dotcode_write_tensor((struct dotcode_tensor*)data, write_header, os);
00096     break;
00097   case DOTCODE_GRID:
00098     err = dotcode_write_grid((struct dotcode_grid*)data, write_header, os);
00099     break;
00100   default:
00101     err = g_error_new(DOTCODE_WRITE_BINARY_DATA_GERROR_DOMAIN, 171, "libdotcode::read_binary_data::read_dotcode_typed_file: Can't recognize dotcode data type (%d/%s)", t, dotcode_string_from_type2(t));
00102     return err;
00103   }
00104   return err;
00105 }
00106 
00107 
00108 GError* dotcode_write_sstring(const char* str, gboolean write_header, GOutputStream *os) {
00109   GError* err=NULL;
00110   /*We need to write out the trailing NULL. It's what Craig's code
00111     does. WE DON'T RELY ON THE TRAILING NULL BEING IN THE STREAM,
00112     THO. That way lies security vulnerabilities!*/
00113   int len = strlen(str) + 1;
00114   GError *e = NULL;
00115   if(write_header) {
00116     e = dotcode_write_sstring(dotcode_string_from_type2(DOTCODE_SSTRING), FALSE, os);
00117     if(e != NULL) return err;
00118   }
00119   e = dotcode_write_int(len, FALSE, os);
00120   if(e != NULL) {
00121     g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_sstring: error writing string length %d (%s)", len, str);
00122     g_error_free(e);
00123     return err;
00124   }
00125   gsize written;
00126   if((!g_output_stream_write_all(os, str, len, &written, NULL, &e)) || (len != written) || (e != NULL)) {
00127     if(len != written) {
00128       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_sstring: error writing string: (%s) len(%d) and amount written(%lu) differ!", str, len, (long unsigned int)written);
00129     }else{
00130       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_sstring: error writing string %s!", str);
00131     }
00132     return err;
00133   }
00134   return NULL;
00135 }
00136 
00137 
00138 GError* dotcode_write_int(int val, gboolean write_header, GOutputStream *os) {
00139   GError *err = NULL;
00140   GError *e = NULL;
00141   union int_union_ {
00142     char buffer[DOTCODE_INT_SIZE];
00143     int val;
00144   } int_union;
00145   int_union.val = val;
00146   if(write_header) {
00147     e = dotcode_write_sstring(dotcode_string_from_type2(DOTCODE_INT), FALSE, os);
00148     if(e != NULL) return err;
00149   }
00150   gsize written;
00151   if((!g_output_stream_write_all(os, int_union.buffer, DOTCODE_INT_SIZE, &written, NULL, &e)) || (DOTCODE_INT_SIZE != written) || (e != NULL)) {
00152     if(DOTCODE_INT_SIZE != written) {
00153       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_int: error writing int: (%d) len(%d) and amount written(%lu) differ!", val, DOTCODE_INT_SIZE, (long unsigned int)written);
00154     }else{
00155       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_int: error writing int %d!", val);
00156     }
00157     return err;
00158   }
00159   return NULL;
00160 }
00161 
00162 
00163 GError* dotcode_write_float8(double val, gboolean write_header, GOutputStream *os) {
00164   GError *err = NULL;
00165   GError *e = NULL;
00166   union float8_union_ {
00167     char buffer[DOTCODE_FLOAT8_SIZE];
00168     double val;
00169   } the_union;
00170   the_union.val = val;
00171   gsize written;
00172   if(write_header) {
00173     e = dotcode_write_sstring(dotcode_string_from_type2(DOTCODE_FLOAT8), FALSE, os);
00174     if(e != NULL) return err;
00175   }
00176   if((!g_output_stream_write_all(os, the_union.buffer, DOTCODE_FLOAT8_SIZE, &written, NULL, &e)) || (DOTCODE_FLOAT8_SIZE != written) || (e != NULL)) {
00177     if(DOTCODE_FLOAT8_SIZE != written) {
00178       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_float8: error writing float8: (%g) len(%d) and amount written(%lu) differ!", val, DOTCODE_FLOAT8_SIZE, (long unsigned int)written);
00179     }else{
00180       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_float8: error writing float8 %g!", val);
00181     }
00182     return err;
00183   }
00184   return NULL;
00185 }
00186 
00187 
00188 GError* dotcode_write_float4(float val, gboolean write_header, GOutputStream *os) {
00189   GError *err = NULL;
00190   GError *e = NULL;
00191   union float4_union_ {
00192     char buffer[DOTCODE_FLOAT4_SIZE];
00193     float val;
00194   } the_union;
00195   the_union.val = val;
00196   gsize written;
00197   if(write_header) {
00198     e = dotcode_write_sstring(dotcode_string_from_type2(DOTCODE_FLOAT4), FALSE, os);
00199     if(e != NULL) return err;
00200   }
00201   if((!g_output_stream_write_all(os, the_union.buffer, DOTCODE_FLOAT4_SIZE, &written, NULL, &e)) || (DOTCODE_FLOAT4_SIZE != written) || (e != NULL)) {
00202     if(DOTCODE_FLOAT4_SIZE != written) {
00203       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_float8: error writing float8: (%g) len(%d) and amount written(%lu) differ!", val, DOTCODE_FLOAT4_SIZE, (long unsigned int)written);
00204     }else{
00205       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_float8: error writing float8 %g!", val);
00206     }
00207     return err;
00208   }
00209   return NULL;
00210 }
00211 
00212 
00213 GError* dotcode_write_vector(const struct dotcode_vector* val, gboolean write_header, GOutputStream *os) {
00214   return g_error_new(DOTCODE_WRITE_BINARY_DATA_GERROR_DOMAIN, DOTCODE_ERROR_NOTIMPLEMENTED, "libdotcode::write_binary_data::write_vector: function not yet implmented.\n");
00215 }
00216 
00217 GError* dotcode_write_array(const struct dotcode_array* val, gboolean write_header, GOutputStream *os) {
00218   GError *err = NULL;
00219   GError *e = NULL;
00220   if(write_header) {
00221     GString *s = g_string_new("");
00222     g_string_printf(s, "%s<%s>", dotcode_string_from_type2(DOTCODE_ARRAY), dotcode_string_from_type2(val->t));
00223     e = dotcode_write_sstring(s->str, FALSE, os);
00224     g_string_free(s, TRUE);
00225     if(e != NULL) return err;
00226   }
00227   e = dotcode_write_int(val->imin, FALSE, os);
00228   if(e != NULL) {
00229     g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_array: error writing integer imin (%d) to output stream.", val->imin);
00230     return err;
00231   }
00232   e = dotcode_write_int(val->imax, FALSE, os);
00233   if(e != NULL) {
00234     g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_array: error writing integer imax (%d) to output stream.", val->imax);
00235     return err;
00236   }
00237   char* str;
00238   for(int i=0; i<((val->imax)-(val->imin)+1); i++) {
00239     switch(val->t) {
00240     case DOTCODE_FLOAT8:
00241       e = dotcode_write_float8(((double*)(val->storage))[i], FALSE, os);
00242       break;
00243     case DOTCODE_FLOAT4:
00244       e = dotcode_write_float4(((float*)(val->storage))[i], FALSE, os);
00245       break;
00246     case DOTCODE_INT:
00247       e = dotcode_write_int(((int*)(val->storage))[i], FALSE, os);
00248       break;
00249     default:
00250       return g_error_new(DOTCODE_WRITE_BINARY_DATA_GERROR_DOMAIN, 1, "libdotcode::write_binary_data::write_array: error writing array data to stream: unknown dotcode type %d (%s)", val->t, str=dotcode_string_from_type(val->t));
00251       g_free(str);
00252     }
00253     if(e != NULL) {
00254       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_array: error writing %dth (array index %d) to output stream.", i, i+val->imin);
00255       return err;
00256     }
00257   }
00258   return NULL;
00259 }
00260 
00261 GError* dotcode_write_grid(const struct dotcode_grid* grid, gboolean write_header, GOutputStream *os) {
00262   GError *err;
00263   GError *e = NULL;
00264   if(write_header) {
00265     GString *s = g_string_new("");
00266     g_string_printf(s, "Grid<%s>", dotcode_string_from_type2(grid->gridsites[0]->t));
00267     e = dotcode_write_sstring(s->str, FALSE, os);
00268     g_string_free(s, TRUE);
00269     if(e != NULL) return err;
00270   }
00271   /*First, the gridspec*/
00272   e = dotcode_write_sstring("GridSpec", FALSE, os);
00273   if(e != NULL) {
00274     g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_grid: error writing \"GridSpec\" to output stream.");
00275     return err;
00276   }
00277   e = dotcode_write_sstring("2.0", FALSE, os);
00278   if(e != NULL) {
00279     g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_grid: error writing \"2.0\" to output stream.");
00280     return err;
00281   }
00282   for(int i=0; i<3; i++) {
00283     e = dotcode_write_array(grid->gridsites[i], FALSE, os);
00284     if(e != NULL) {
00285       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_grid: error writing index array %d to output stream.", i);
00286       return err;
00287     }
00288   }
00289   for(int i=0; i<3; i++) {
00290     e = dotcode_write_int(grid->Ng[i], FALSE, os);
00291     if(e != NULL) {
00292       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_grid: error writing Ng[%d] to output stream.", i);
00293       return err;
00294     }
00295   }
00296   /*Then, the tensor*/
00297   e = dotcode_write_tensor(grid->data, TRUE, os);
00298   if(e != NULL) {
00299     g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_grid: error writing tensor to output stream.");
00300     return err;
00301   }
00302   return NULL;
00303 }
00304 
00305 GError* dotcode_write_tensor(const struct dotcode_tensor* tensor, gboolean write_header, GOutputStream *os) {
00306   GError *err = NULL;
00307   GError *e = NULL;
00308   char* str;
00309   if(write_header) {
00310     GString *s = g_string_new("");
00311     g_string_printf(s, "%s<%s>", dotcode_string_from_type2(DOTCODE_TENSOR), dotcode_string_from_type2(tensor->t));
00312     e = dotcode_write_sstring(s->str, FALSE, os);
00313     g_string_free(s, TRUE);
00314     if(e != NULL) return err;
00315   }
00316   e = dotcode_write_sstring(tensor->metadata, FALSE, os);
00317   if(e != NULL) {
00318     g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_tensor: error writing metadata (%s) to output stream", tensor->metadata);
00319     return err;
00320   }
00321   e = dotcode_write_int(tensor->Nd, FALSE, os);
00322   if(e != NULL) {
00323     g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_tensor: error writing number of dimensions (%d) to output stream", tensor->Nd);
00324     return err;
00325   }
00326   for(int d=0; d<tensor->Nd; d++) {
00327     for(int m=0; m<2; m++) {
00328       e = dotcode_write_int(tensor->indices[m+2*d], FALSE, os);
00329       if(e != NULL) {
00330   g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_tensor: error writing %s for dimension %d to output stream", m?"imax":"imin", tensor->Nd);
00331   return err;
00332       }
00333     }
00334   }
00335   /*Walk through the array, writing the values. Since our in-memory
00336     representation is identical to the on-disk representation, we're
00337     good to go.*/
00338   long unsigned int size=1;
00339   for(int d=0; d<tensor->Nd; d++) size *= tensor->indices[1+2*d] - tensor->indices[2*d] + 1;
00340   for(long unsigned int i=0; i<size; i++) {
00341     switch(tensor->t) {
00342     case DOTCODE_FLOAT8:
00343       e = dotcode_write_float8(((double*)(tensor->data))[i], FALSE, os);
00344       break;
00345     case DOTCODE_FLOAT4:
00346       e = dotcode_write_float4(((float*)(tensor->data))[i], FALSE, os);
00347       break;
00348     case DOTCODE_INT:
00349       e = dotcode_write_int(((int*)(tensor->data))[i], FALSE, os);
00350       break;
00351     default:
00352       return g_error_new(DOTCODE_WRITE_BINARY_DATA_GERROR_DOMAIN, 1, "libdotcode::write_binary_data::write_tensor: error writing tensor data to stream: unknown dotcode type %d (%s)", tensor->t, str=dotcode_string_from_type(tensor->t));
00353       g_free(str);
00354     }
00355     if(e != NULL) {
00356       g_propagate_prefixed_error(&err, e, "libdotcode::write_binary_data::write_tensor: error writing %luth datum to output stream.", i);
00357       return err;
00358     }
00359   }
00360   return NULL;
00361 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines