|
funkalicious 0.1
|
00001 /* 00002 ** binary_data_common.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:39:39 2009 Johnny Q. Hacker 00024 ** Last update Sun May 12 01:17:25 2002 Speed Blue 00025 */ 00026 00027 #include <stdlib.h> 00028 #include <string.h> 00029 #include <glib-2.0/glib.h> 00030 #include <stdio.h> 00031 #include "binary_data_common.h" 00032 00033 #define DOTCODE_BINARY_DATA_COMMON_GERROR_DOMAN 43712 00034 00035 enum dotcode_type dotcode_type_from_string(const char* s) { 00036 if(!g_ascii_strncasecmp(s, "float8", strlen("float8"))){ 00037 return DOTCODE_FLOAT8; 00038 }else if(!g_ascii_strncasecmp(s, "float4", strlen("float4"))){ 00039 return DOTCODE_FLOAT4; 00040 }else if(!g_ascii_strncasecmp(s, "int", strlen("int"))){ 00041 return DOTCODE_INT; 00042 }else if(!g_ascii_strncasecmp(s, "int4", strlen("int4"))){ 00043 return DOTCODE_INT; 00044 }else if(!g_ascii_strncasecmp(s, "Vector", strlen("Vector"))){ 00045 return DOTCODE_VECTOR; 00046 }else if(!g_ascii_strncasecmp(s, "Array", strlen("Array"))){ 00047 return DOTCODE_ARRAY; 00048 }else if(!g_ascii_strncasecmp(s, "Tensor", strlen("Tensor"))){ 00049 return DOTCODE_TENSOR; 00050 }else if(!g_ascii_strncasecmp(s, "Grid", strlen("Grid"))){ 00051 return DOTCODE_GRID; 00052 }else if(!g_ascii_strncasecmp(s, "SString", strlen("SString"))){ 00053 return DOTCODE_SSTRING; 00054 } 00055 return DOTCODE_INVALID_TYPE; 00056 } 00057 00058 char* dotcode_string_from_type(enum dotcode_type t) { 00059 const char* s = dotcode_string_from_type2(t); 00060 if(s == NULL) return NULL; 00061 return g_strdup(s); 00062 } 00063 00064 const char* dotcode_string_from_type2(enum dotcode_type t) { 00065 switch(t) { 00066 case DOTCODE_FLOAT8: 00067 return g_strdup("float8"); 00068 case DOTCODE_FLOAT4: 00069 return g_strdup("float4"); 00070 case DOTCODE_INT: 00071 return g_strdup("int4"); 00072 case DOTCODE_VECTOR: 00073 return g_strdup("Vector"); 00074 case DOTCODE_ARRAY: 00075 return g_strdup("Array"); 00076 case DOTCODE_TENSOR: 00077 return g_strdup("Tensor"); 00078 case DOTCODE_GRID: 00079 return g_strdup("Grid"); 00080 case DOTCODE_SSTRING: 00081 return g_strdup("SString"); 00082 case DOTCODE_INVALID_TYPE: 00083 return g_strdup("INVALID TYPE"); 00084 default: 00085 return NULL; 00086 } 00087 return NULL; 00088 } 00089 00090 void flip_endian(char* buffer, int num_bytes) { 00091 int i, j; 00092 char c; 00093 int max = num_bytes >> 1; 00094 for(i=0, j=(num_bytes-1); i<max; ++i, --j) { 00095 c=buffer[i]; 00096 buffer[i]=buffer[j]; 00097 buffer[j]=c; 00098 } 00099 } 00100 00101 /*It is assumed that ptr points to a buffer of count objects.*/ 00102 void dotcode_free_type(enum dotcode_type t, void* ptr, long unsigned int count, GError **err, gboolean free_struct) { 00103 GError *e = NULL; 00104 /*If we have a buffer of a simple type, just free it.*/ 00105 switch(t) { 00106 case DOTCODE_FLOAT8: 00107 case DOTCODE_FLOAT4: 00108 case DOTCODE_INT: 00109 case DOTCODE_SSTRING: 00110 free(ptr); 00111 return; 00112 default: 00113 break; 00114 } 00115 long unsigned int size = 1; 00116 for(long unsigned int i=0; i<count; i++) { 00117 /*Since these are freeing an array of actual structures (as 00118 opposed to an array of pointers to structures) we don't need to 00119 free the struct at the end.*/ 00120 switch(t) { 00121 case DOTCODE_VECTOR: 00122 dotcode_free_type(((struct dotcode_vector*)ptr)->t, 00123 ((struct dotcode_vector*)ptr)->data, 00124 3, 00125 &e, 00126 FALSE); 00127 break; 00128 case DOTCODE_ARRAY: 00129 dotcode_free_type(((struct dotcode_array*)ptr)->t, 00130 ((struct dotcode_array*)ptr)->storage, 00131 (((struct dotcode_array*)ptr)->imax - ((struct dotcode_array*)ptr)->imax +1), 00132 &e, 00133 FALSE); 00134 break; 00135 case DOTCODE_TENSOR: 00136 /*need to know how many items there are, for the derived types 00137 (irrelevant for float, int)*/ 00138 size = 1; 00139 for(long unsigned int j=0; j<((struct dotcode_tensor*)ptr)->Nd; j++) 00140 size*=((((struct dotcode_tensor*)ptr)->indices)[2*j+1]-(((struct dotcode_tensor*)ptr)->indices)[2*j]+1); 00141 /*need to know how many items there are*/ 00142 dotcode_free_type(((struct dotcode_tensor*)ptr)->t, 00143 ((struct dotcode_tensor*)ptr)->data, 00144 size, 00145 &e, 00146 FALSE); 00147 free(((struct dotcode_tensor*)ptr)->indices); 00148 free(((struct dotcode_tensor*)ptr)->metadata); 00149 break; 00150 case DOTCODE_GRID: 00151 for(int i=0; i<3; i++) { 00152 dotcode_free_type(DOTCODE_ARRAY, 00153 ((struct dotcode_grid*)ptr)->gridsites[i], 00154 1, 00155 &e, 00156 TRUE); 00157 } 00158 dotcode_free_type(DOTCODE_TENSOR, 00159 ((struct dotcode_grid*)ptr)->data, 00160 1, 00161 &e, 00162 TRUE); 00163 break; 00164 default: 00165 *err = g_error_new(DOTCODE_BINARY_DATA_COMMON_GERROR_DOMAN, 1, "dotcode::binary_data_common::dotcode_free_type: Invalid type %d (%s)", t, dotcode_string_from_type2(t)); 00166 return; 00167 } 00168 if(e != NULL) { 00169 g_propagate_prefixed_error(err, e, "dotcode::binary_data_common::dotcode_free_type: Failure when freeing type %d (%s)", t, dotcode_string_from_type2(t)); 00170 return; 00171 } 00172 } 00173 if(free_struct) { 00174 switch(t) { 00175 case DOTCODE_VECTOR: 00176 free((struct dotcode_vector*)ptr); 00177 break; 00178 case DOTCODE_ARRAY: 00179 free((struct dotcode_array*)ptr); 00180 break; 00181 case DOTCODE_TENSOR: 00182 free((struct dotcode_tensor*)ptr); 00183 break; 00184 case DOTCODE_GRID: 00185 free((struct dotcode_grid*)ptr); 00186 break; 00187 default: 00188 break; 00189 } 00190 } 00191 } 00192 00193 /**Determines a type from a type string. 00194 *\param t1 is the first item in the char** returned from g_strsplit(str, "<", 1) 00195 *\param t2 is the second string in the char** 00196 *\param tlist a pointer to an *existing* NULL GList*. 00197 *Types may be nested, hence the need for a GList of types. 00198 *The data in the GList is enum dotcode_type. 00199 *NOTE that the tlist MUST be initialized to NULL before calling this 00200 * function, as it's recursive. 00201 */ 00202 static void determine_templated_type_(char* t1, char*t2 , GList** tlist, GError **err) { 00203 if(t1 == NULL) return; 00204 enum dotcode_type *t = (enum dotcode_type*)malloc(sizeof(enum dotcode_type)); 00205 if(t == NULL) { 00206 *err = g_error_new(DOTCODE_BINARY_DATA_COMMON_GERROR_DOMAN, 180, "dotcode::read_binary_data::read_vector: ERROR failed to allocate storage for a new vector."); 00207 } 00208 *t = dotcode_type_from_string(t1); 00209 if(t2 != NULL) { 00210 /*Here's the recursive step.*/ 00211 char** sstr = g_strsplit(t2, "<", 2); 00212 determine_templated_type_(sstr[0], sstr[1], tlist, err); 00213 g_strfreev(sstr); 00214 } 00215 *tlist = g_list_prepend(*tlist, t); 00216 } 00217 00218 /**This is the front-end to the determine_templated_type_ function. 00219 *\param str is the list 00220 *\param tlist a pointer to an *existing* GList*, which will be set to NULL. 00221 *\param err is a pointer to an existing NULL GError* 00222 *\note the tlist is a GList of pointers to dotcode_types, in order of occurrance. 00223 * Thus, a GList of a, b, c means a templated with b, which is in turn 00224 * templated with c. 00225 */ 00226 void dotcode_determine_templated_type(const char* str, GList** tlist, GError **err) { 00227 *tlist = NULL; 00228 /*Remove invalid chars; valid are alphanumeric, underscoe, and >; this will 00229 remove '>', but that's fine; we don't really want it. 00230 */ 00231 char* dstr = g_strdup(str); 00232 g_strcanon(dstr, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_<", ' '); 00233 g_strchug(dstr); 00234 char** sstr = g_strsplit(dstr, "<", 2); 00235 determine_templated_type_(sstr[0], sstr[1], tlist, err); 00236 g_free(dstr); 00237 g_strfreev(sstr); 00238 } 00239