k-dot-p 0.1

matdb-dotcode.c++

Go to the documentation of this file.
00001 /*
00002  * matdb-dotcode: reads in Craig's Dotcode materials database.
00003 
00004  Copyright (C) 2009 Joseph Pingenot
00005 
00006  This program is free software: you can redistribute it and/or modify
00007  it under the terms of the GNU Affero General Public License as published by
00008  the Free Software Foundation, either version 3 of the License, or
00009  (at your option) any later version.
00010 
00011  This program is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  GNU Affero General Public License for more details.
00015 
00016  You should have received a copy of the GNU Affero General Public License
00017  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00020 #include <stdio.h>
00021 #include <strings.h>
00022 #include <stdlib.h>
00023 #include "config.h"
00024 #include <libmodelxx/matdb.h++>
00025 #include <libmodelxx/matdb-dotcode.h++>
00026 
00027 namespace kdotp {
00028   namespace libmodelxx {
00029     namespace structure {
00030 
00031 #ifdef DEBUG
00032 #undef DEBUG
00033 #endif
00034 #ifdef DEBUG_2
00035 #undef DEBUG_2
00036 #endif
00037 
00038       /*Functions to be used by the hash.*/
00039       static void destroy_string(gpointer data) {
00040   free((char*)data);
00041       }
00042       static void destroy_double(gpointer data){
00043   free((double*)data);
00044       }
00045       static void destroy_inner_bowhash(gpointer data) {
00046   g_hash_table_unref((GHashTable*)data);
00047       }
00048 
00049       int insert_into_matdb(struct matdb *mdb, struct matdb_material **mat, struct matdb_bowing **bow) {
00050   if((*mat) != NULL) {
00051 #ifdef DEBUG
00052     fprintf(stderr, "inserting material %s\n", (*mat)->name->str);
00053 #endif
00054     g_hash_table_insert(mdb->materials, (gpointer)g_strdup((*mat)->name->str), (gpointer)(*mat));
00055     (*mat) = NULL;
00056   }
00057   if((*bow) != NULL) {
00058 #ifdef DEBUG
00059     fprintf(stderr, "inserting bowing %s:%s\n", (*bow)->from->str, (*bow)->to->str);
00060 #endif
00061     /*Inner table*/
00062     GHashTable *it;
00063     if((it=(GHashTable*)g_hash_table_lookup(mdb->bowings, (*bow)->from->str)) == NULL) {
00064       if((it = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_inner_bowhash)) == NULL) {
00065         (*bow) = NULL;
00066         return 1;
00067       }
00068       g_hash_table_insert(mdb->bowings, (*bow)->from->str, it);
00069 #ifdef DEBUG
00070       fprintf(stderr, "Got new hash table (from=%s)\n", (*bow)->from->str);
00071 #endif
00072     }
00073     g_hash_table_insert(it, (gpointer)g_strdup((*bow)->to->str), (gpointer)(*bow));
00074     (*bow) = NULL;
00075   }
00076   return 0;
00077       }
00078 
00079       /*Removes leading and trailing whitespace, comments, and reduces
00080   redundant whitespace down to one tab, makes an empty line an empty string.*/
00081       static void prettify_line(char *line) {
00082   register char *look;
00083   register char *write;
00084   register int in_whitespace;
00085   register int leading_whitespace;
00086   for(look=write=line, in_whitespace=0, leading_whitespace=1; *look != '\0'; look++) {
00087 #ifdef DEBUG_2
00088     fprintf(stderr, " look=%d(%c) write=%d(%c) in_whitespace=%d leading_whitespace=%d: ", (look-line), *look, (write-line), *write, in_whitespace, leading_whitespace);
00089 #endif
00090     if(*look == '#') {
00091 #ifdef DEBUG_2
00092       fprintf(stderr, "comment\n");
00093 #endif
00094       *write = '\0';
00095       break;
00096     }
00097     switch(*look) {
00098     case ' ':
00099     case '\n':
00100     case '\t':
00101 #ifdef DEBUG_2
00102       fprintf(stderr, "whitespace\n");
00103 #endif
00104     if((!leading_whitespace) && (!in_whitespace)) *write++ = '\t';
00105     in_whitespace=1;
00106     break;
00107     default:
00108 #ifdef DEBUG_2
00109       fprintf(stderr, "default\n");
00110 #endif
00111       *write++ = *look;
00112       in_whitespace=leading_whitespace=0;
00113     }
00114   }
00115   *write='\0';
00116   for(look=write=line; *look != '\0'; look++) {
00117     switch(*look) {
00118     case ' ':
00119     case '\n':
00120     case '\t':
00121       if(*(look+1) == '\0') {
00122         *look = '\0';
00123       }
00124     }
00125   }
00126       }
00127 
00128       /*Error values:
00129        *   0: success
00130        *   1: failure malloc'ing / initializing mdb struct
00131        *   2: failure opening file.
00132        *   4: failure reading line.
00133        *   8: warning reading line: no tab separator (line parsing error)
00134        *  16: warning reading line: bad section declaration
00135        *  32: warning reading line: unable to allocate material struct.
00136        *  64: warning reading line: ignored line (unallocated material struct)
00137        * 128: warning reading line: unable to allocate bowing struct
00138        * 256: warning reading line: ignored line (unallocated bowing struct)
00139        * 512: warning reading file: improper section detected (programming
00140        *   error)
00141        *1024: warning reading file: no : separator in bowing materials
00142        *   description.
00143        *2048: warning reading file: unable to read numeric value for property.
00144        */
00145       struct matdb* read_matdb_dotcode(const GString *name, int* err) {
00146 #ifdef DEBUG_2
00147   fprintf(stderr, "in read_matdb_dotcode(%s, %d)\n", name->str, *err);
00148 #endif
00149   *err=0;
00150   struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb));
00151   if(mdb == NULL) {*err = 1; return NULL;}
00152 
00153   double *value;
00154   if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) {
00155     *err = 1;
00156     free(mdb);
00157     return NULL;
00158   }
00159   if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) {
00160     *err = 1;
00161     g_hash_table_unref(mdb->materials);
00162     free(mdb);
00163     return NULL;
00164   }
00165   struct matdb_material *mat = NULL;
00166   struct matdb_bowing *bow = NULL;
00167   /*Valid sections:
00168    * 0 (no/global section)
00169    * 1 (material)
00170    * 2 (bow)
00171    */
00172   int section=0;
00173   size_t n;
00174   char *line;
00175   FILE *infile = fopen(name->str, "r");
00176   if(infile == NULL) {
00177     g_hash_table_unref(mdb->materials);
00178     g_hash_table_unref(mdb->bowings);
00179     free(mdb);
00180     *err=2;
00181     return NULL;
00182 #ifdef DEBUG_2
00183   }else{
00184     fprintf(stderr, "infile=%x\n", (unsigned int)infile);
00185 #endif
00186   }
00187   int val;
00188   while(!feof(infile)) {
00189 #ifdef DEBUG
00190     fprintf(stderr, "mat=%x(%s), bow=%x(%s:%s)\n", (unsigned int)mat, mat?mat->name->str:"", (unsigned int)bow, bow?bow->from->str:"", bow?bow->to->str:"");
00191 #endif
00192     line=NULL;
00193     if((val = getline(&line, &n, infile)) == -1) {
00194 #ifdef DEBUG_2
00195       fprintf(stderr, "getline returned %d\n", val); 
00196 #endif
00197       if(!feof(infile)) *err = 4;
00198       //fclose(infile);
00199       break;
00200     }
00201 #ifdef DEBUG_2
00202     fprintf(stderr, "line=(%s)\n", line);
00203 #endif
00204     prettify_line(line);
00205 #ifdef DEBUG
00206     fprintf(stderr, "%d: prettified line=(%s)\n", section, line);
00207 #endif
00208     if(*line == '\0') {
00209       free(line);
00210       continue;
00211     }
00212     char *i = index(line, '\t');
00213     if(i == NULL) {
00214       *err &= 8;
00215     }
00216     *i++ = '\0';
00217     /*At this point, we have line which stores the first word on the
00218       line, and i which stores the second word on the line.
00219     */
00220     char *to;
00221     GHashTable *ht;
00222 #ifdef DEBUG_2
00223     fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i);
00224 #endif
00225     /*If we have a material or bowing underway, save it off*/
00226     if(strcasecmp(line, "material") == 0) {
00227       insert_into_matdb(mdb, &mat, &bow);
00228       if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) {
00229         *err &= 32;
00230       }
00231       if((mat->name = g_string_new(i)) == NULL) {
00232         *err &= 32;
00233         free(mat);
00234         section=0;
00235         continue;
00236       }
00237       if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
00238         *err &= 32;
00239         g_string_free(mat->name, TRUE);
00240         free(bow);
00241         section=0;
00242         continue;
00243       }
00244 #ifdef DEBUG_2
00245       fprintf(stderr, "new material (%s):\n", i);
00246 #endif
00247       section=1;
00248     }else if(strcasecmp(line, "bow") == 0) {
00249       insert_into_matdb(mdb, &mat, &bow);
00250       if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) {
00251         *err &= 128;
00252       }
00253       if((to = index(i, ':')) == NULL) {
00254         *err &= 1024;
00255         free(bow);
00256         section=0;
00257         continue;
00258       }
00259       *to++ = '\0';
00260       /*Same trick as before, but i now stores the from material,
00261         and to the to material
00262       */
00263       if((bow->from = g_string_new(i)) == NULL) {
00264         *err &= 128;
00265         free(bow);
00266         section=0;
00267         continue;
00268       }
00269       if((bow->to = g_string_new(to)) == NULL) {
00270         *err &= 128;
00271         g_string_free(bow->from, TRUE);
00272         free(bow);
00273         section=0;
00274         continue;
00275       }
00276       if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
00277         *err &= 128;
00278         g_string_free(bow->to, TRUE);
00279         g_string_free(bow->from, TRUE);
00280         free(bow);
00281         section=0;
00282         continue;
00283       }
00284 #ifdef DEBUG_2
00285       fprintf(stderr, "new bowing (%s:%s):\n", i, to);
00286 #endif
00287       section=2;
00288     }else{
00289 #ifdef DEBUG
00290       fprintf(stderr, "\t%d/%s\t", section, line);
00291 #endif
00292       /*Process a property.*/
00293       switch(section) {
00294       case 1:
00295 #ifdef DEBUG
00296         fprintf(stderr, "(1)\t");
00297 #endif
00298         ht = mat->properties;
00299         break;
00300       case 2:
00301 #ifdef DEBUG
00302         fprintf(stderr, "(2)\t");
00303 #endif
00304         ht = bow->properties;
00305         break;
00306       default:
00307 #ifdef DEBUG
00308         fprintf(stderr, "(default)\t");
00309 #endif
00310         *err &= 16;
00311         section = 0;
00312       }
00313       if(section == 0) {
00314 #ifdef DEBUG
00315         fprintf(stderr, "section was 0\n");
00316 #endif
00317         continue;
00318       }
00319       if((value = (double*)malloc(sizeof(double))) == NULL) {
00320         *err &= 2048;
00321 #ifdef DEBUG
00322         fprintf(stderr, "malloc of value failed\n");
00323 #endif
00324         continue;
00325       }
00326       int num;
00327       if((num=sscanf(i, " %lg", value)) != 1) {
00328         *err &= 2048;
00329         free(value);
00330 #ifdef DEBUG
00331         fprintf(stderr, "bad sscanf to get value (scanned \"%s\", returned %d)\n", i, num);
00332 #endif
00333         continue;
00334       }
00335       g_hash_table_insert(ht, g_strdup(line), value);
00336 #ifdef DEBUG
00337       fprintf(stderr, "%g(%s)\n", *value, line);
00338 #endif
00339     }
00340     free(line);
00341     line=i=to=NULL;
00342     value=NULL;
00343   }
00344   fclose(infile);
00345   insert_into_matdb(mdb, &mat, &bow);
00346   return mdb;
00347       }
00348 
00349 
00350     }
00351   }
00352 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines