|
funkalicious 0.1
|
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 }