X-Git-Url: http://git.maemo.org/git/?p=scdataviz;a=blobdiff_plain;f=src%2Fmatdb-dotcode.c;fp=src%2Fmatdb-dotcode.c;h=df195fb887b17bb4c5542da58b7b0efb3330c39e;hp=0000000000000000000000000000000000000000;hb=ca8d26a012451771595cf54194888b1984c5dd17;hpb=b5cfdf4d4f01bf9f8def7d69fd58e254886ed2d5 diff --git a/src/matdb-dotcode.c b/src/matdb-dotcode.c new file mode 100644 index 0000000..df195fb --- /dev/null +++ b/src/matdb-dotcode.c @@ -0,0 +1,346 @@ +/* + * matdb-dotcode: reads in Craig's Dotcode materials database. + + + + Copyright (C) 2008 Joseph Pingenot + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +*/ + +#include +#define _GNU_SOURCE +#include +#include +#include + +#ifdef DEBUG +#undef DEBUG +#endif +#ifdef DEBUG_2 +#undef DEBUG_2 +#endif + +/*Functions to be used by the hash.*/ +static void destroy_string(gpointer data) { + free((char*)data); +} +static void destroy_double(gpointer data){ + free((double*)data); +} +static void destroy_inner_bowhash(gpointer data) { + g_hash_table_unref(data); +} + +int insert_into_matdb(struct matdb *mdb, struct matdb_material **mat, struct matdb_bowing **bow) { + if((*mat) != NULL) { +#ifdef DEBUG + fprintf(stderr, "inserting material %s\n", (*mat)->name->str); +#endif + g_hash_table_insert(mdb->materials, (gpointer)g_strdup((*mat)->name->str), (gpointer)(*mat)); + (*mat) = NULL; + } + if((*bow) != NULL) { +#ifdef DEBUG + fprintf(stderr, "inserting bowing %s:%s\n", (*bow)->from->str, (*bow)->to->str); +#endif + /*Inner table*/ + GHashTable *it; + if((it=g_hash_table_lookup(mdb->bowings, (*bow)->from->str)) == NULL) { + if((it = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_inner_bowhash)) == NULL) { + (*bow) = NULL; + return 1; + } + g_hash_table_insert(mdb->bowings, (*bow)->from->str, it); + #ifdef DEBUG + fprintf(stderr, "Got new hash table (from=%s)\n", (*bow)->from->str); + #endif + } + g_hash_table_insert(it, (gpointer)g_strdup((*bow)->to->str), (gpointer)(*bow)); + (*bow) = NULL; + } + return 0; +} + +/*Removes leading and trailing whitespace, comments, and reduces + redundant whitespace down to one tab, makes an empty line an empty string.*/ +static void prettify_line(char *line) { + register char *look; + register char *write; + register int in_whitespace; + register int leading_whitespace; + for(look=write=line, in_whitespace=0, leading_whitespace=1; *look != '\0'; look++) { +#ifdef DEBUG_2 + fprintf(stderr, " look=%d(%c) write=%d(%c) in_whitespace=%d leading_whitespace=%d: ", (look-line), *look, (write-line), *write, in_whitespace, leading_whitespace); +#endif + if(*look == '#') { +#ifdef DEBUG_2 + fprintf(stderr, "comment\n"); +#endif + *write = '\0'; + break; + } + switch(*look) { + case ' ': + case '\n': + case '\t': +#ifdef DEBUG_2 + fprintf(stderr, "whitespace\n"); +#endif + if((!leading_whitespace) && (!in_whitespace)) *write++ = '\t'; + in_whitespace=1; + break; + default: +#ifdef DEBUG_2 + fprintf(stderr, "default\n"); +#endif + *write++ = *look; + in_whitespace=leading_whitespace=0; + } + } + *write='\0'; + for(look=write=line; *look != '\0'; look++) { + switch(*look) { + case ' ': + case '\n': + case '\t': + if(*(look+1) == '\0') { + *look = '\0'; + } + } + } +} + +/*Error values: + * 0: success + * 1: failure malloc'ing / initializing mdb struct + * 2: failure opening file. + * 4: failure reading line. + * 8: warning reading line: no tab separator (line parsing error) + * 16: warning reading line: bad section declaration + * 32: warning reading line: unable to allocate material struct. + * 64: warning reading line: ignored line (unallocated material struct) + * 128: warning reading line: unable to allocate bowing struct + * 256: warning reading line: ignored line (unallocated bowing struct) + * 512: warning reading file: improper section detected (programming + * error) + *1024: warning reading file: no : separator in bowing materials + * description. + *2048: warning reading file: unable to read numeric value for property. + */ +struct matdb* read_matdb_dotcode(const GString *name, int* err) { +#ifdef DEBUG_2 + fprintf(stderr, "in read_matdb_dotcode(%s, %d)\n", name->str, *err); +#endif + *err=0; + struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb)); + if(mdb == NULL) {*err = 1; return NULL;} + + double *value; + if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) { + *err = 1; + free(mdb); + return NULL; + } + if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) { + *err = 1; + g_hash_table_unref(mdb->materials); + free(mdb); + return NULL; + } + struct matdb_material *mat = NULL; + struct matdb_bowing *bow = NULL; + /*Valid sections: + * 0 (no/global section) + * 1 (material) + * 2 (bow) + */ + int section=0; + int n; + char *line; + FILE *infile = fopen(name->str, "r"); + if(infile == NULL) { + g_hash_table_unref(mdb->materials); + g_hash_table_unref(mdb->bowings); + free(mdb); + *err=2; + return NULL; +#ifdef DEBUG_2 + }else{ + fprintf(stderr, "infile=%x\n", (unsigned int)infile); +#endif + } + int val; + while(!feof(infile)) { +#ifdef DEBUG + 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:""); +#endif + line=NULL; + if((val = getline(&line, &n, infile)) == -1) { +#ifdef DEBUG_2 + fprintf(stderr, "getline returned %d\n", val); +#endif + if(!feof(infile)) *err = 4; + //fclose(infile); + break; + } +#ifdef DEBUG_2 + fprintf(stderr, "line=(%s)\n", line); +#endif + prettify_line(line); +#ifdef DEBUG + fprintf(stderr, "%d: prettified line=(%s)\n", section, line); +#endif + if(*line == '\0') { + free(line); + continue; + } + char *i = index(line, '\t'); + if(i == NULL) { + *err &= 8; + } + *i++ = '\0'; + /*At this point, we have line which stores the first word on the + line, and i which stores the second word on the line. + */ + char *to; + GHashTable *ht; +#ifdef DEBUG_2 + fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i); +#endif + /*If we have a material or bowing underway, save it off*/ + if(strcasecmp(line, "material") == 0) { + insert_into_matdb(mdb, &mat, &bow); + if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) { + *err &= 32; + } + if((mat->name = g_string_new(i)) == NULL) { + *err &= 32; + free(mat); + section=0; + continue; + } + if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) { + *err &= 32; + g_string_free(mat->name, TRUE); + free(bow); + section=0; + continue; + } +#ifdef DEBUG_2 + fprintf(stderr, "new material (%s):\n", i); +#endif + section=1; + }else if(strcasecmp(line, "bow") == 0) { + insert_into_matdb(mdb, &mat, &bow); + if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) { + *err &= 128; + } + if((to = index(i, ':')) == NULL) { + *err &= 1024; + free(bow); + section=0; + continue; + } + *to++ = '\0'; + /*Same trick as before, but i now stores the from material, + and to the to material + */ + if((bow->from = g_string_new(i)) == NULL) { + *err &= 128; + free(bow); + section=0; + continue; + } + if((bow->to = g_string_new(to)) == NULL) { + *err &= 128; + g_string_free(bow->from, TRUE); + free(bow); + section=0; + continue; + } + if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) { + *err &= 128; + g_string_free(bow->to, TRUE); + g_string_free(bow->from, TRUE); + free(bow); + section=0; + continue; + } +#ifdef DEBUG_2 + fprintf(stderr, "new bowing (%s:%s):\n", i, to); +#endif + section=2; + }else{ + #ifdef DEBUG + fprintf(stderr, "\t%d/%s\t", section, line); + #endif + /*Process a property.*/ + switch(section) { + case 1: + #ifdef DEBUG + fprintf(stderr, "(1)\t"); + #endif + ht = mat->properties; + break; + case 2: + #ifdef DEBUG + fprintf(stderr, "(2)\t"); + #endif + ht = bow->properties; + break; + default: + #ifdef DEBUG + fprintf(stderr, "(default)\t"); + #endif + *err &= 16; + section = 0; + } + if(section == 0) { + #ifdef DEBUG + fprintf(stderr, "section was 0\n"); + #endif + continue; + } + if((value = (double*)malloc(sizeof(double))) == NULL) { + *err &= 2048; + #ifdef DEBUG + fprintf(stderr, "malloc of value failed\n"); + #endif + continue; + } + int num; + if((num=sscanf(i, " %lg", value)) != 1) { + *err &= 2048; + free(value); + #ifdef DEBUG + fprintf(stderr, "bad sscanf to get value (scanned \"%s\", returned %d)\n", i, num); + #endif + continue; + } + g_hash_table_insert(ht, g_strdup(line), value); +#ifdef DEBUG + fprintf(stderr, "%g(%s)\n", *value, line); +#endif + } + free(line); + line=i=to=NULL; + value=NULL; + } + fclose(infile); + insert_into_matdb(mdb, &mat, &bow); + return mdb; +} +