BibTeXq
query a bibtex file
bibtex_entry.c
Go to the documentation of this file.
00001 /*
00002  * This work is licensed under a Creative Commons 
00003  * Attribution-Noncommercial-Share Alike 3.0 United States License.
00004  * 
00005  *    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
00006  * 
00007  * You are free:
00008  * 
00009  *    to Share - to copy, distribute, display, and perform the work
00010  *    to Remix - to make derivative works
00011  * 
00012  * Under the following conditions:
00013  * 
00014  *    Attribution. You must attribute the work in the manner specified by the
00015  *    author or licensor (but not in any way that suggests that they endorse you
00016  *    or your use of the work).
00017  * 
00018  *    Noncommercial. You may not use this work for commercial purposes.
00019  * 
00020  *    Share Alike. If you alter, transform, or build upon this work, you may
00021  *    distribute the resulting work only under the same or similar license to
00022  *    this one.
00023  * 
00024  * For any reuse or distribution, you must make clear to others the license
00025  * terms of this work. The best way to do this is by including this header.
00026  * 
00027  * Any of the above conditions can be waived if you get permission from the
00028  * copyright holder.
00029  * 
00030  * Apart from the remix rights granted under this license, nothing in this
00031  * license impairs or restricts the author's moral rights.
00032  */
00033 
00034 
00046 #include <config.h>
00047 
00048 #include <stdlib.h>
00049 #include <stdio.h>
00050 #include <inttypes.h>
00051 #include <string.h>
00052 #include <assert.h>
00053 #include <ctype.h>
00054 
00055 #ifdef BIBTEXQ_HAVE_DMALLOC
00056 #include <dmalloc.h>
00057 #endif
00058 
00059 #include "bibtex_entry.h"
00060 
00061 
00063 static void remove_extra_spaces(char* str)
00064 {
00065     char* chars;
00066     char* chars_shift;
00067     char  prev_char;
00068     int   len;
00069 
00070     chars = str;
00071 
00072     if (len == 0)
00073     {
00074         return;
00075     }
00076     else if (len == 1 && isspace(*chars))
00077     {
00078         *chars = '\0';
00079         return;
00080     }
00081 
00082     while (*chars != '\0')
00083     {
00084         if (*chars == '\n' || *chars == '\t')
00085         {
00086             chars_shift = chars;
00087             while (*chars_shift != '\0')
00088             {
00089                 *chars_shift = *(chars_shift+1);
00090                 chars_shift++;
00091             }
00092         }
00093         else
00094         {
00095             chars++;
00096         }
00097     }
00098 
00099     chars = str;
00100     prev_char = '\0';
00101     while (*chars != '\0')
00102     {
00103         if (prev_char == ' ' && *chars == ' ')
00104         {
00105             chars_shift = chars;
00106             while (*chars_shift != '\0')
00107             {
00108                 *chars_shift = *(chars_shift+1);
00109                 chars_shift++;
00110             }
00111         }
00112         else
00113         {
00114             prev_char = *chars;
00115             chars++;
00116         }
00117     }
00118 }
00119 
00120 
00133 static void create_bibtex_field
00134 (
00135     Bibtex_field** field_out, 
00136     const char*    name, 
00137     const char*    value
00138 )
00139 {
00140     Bibtex_field* field;
00141 
00142     if (*field_out == NULL)
00143     {
00144         assert(*field_out = malloc(sizeof(Bibtex_field)));
00145         (*field_out)->name = NULL;
00146         (*field_out)->value = NULL;
00147     }
00148     field = *field_out;
00149 
00150     field->name = malloc(sizeof(char)*strlen(name));
00151     field->value = malloc(sizeof(char)*strlen(value));
00152 
00153     strcpy(field->name, name);
00154     strcpy(field->value, value);
00155 
00156     remove_extra_spaces(field->name);
00157     remove_extra_spaces(field->value);
00158 }
00159 
00160 
00169 static void free_bibtex_fields(Bibtex_field** fields, uint32_t num_fields)
00170 {
00171     uint32_t i;
00172 
00173     if (fields == NULL || num_fields == 0)
00174         return;
00175 
00176     for (i = 0; i < num_fields; i++)
00177     {
00178         free(fields[ i ]->name);
00179         free(fields[ i ]->value);
00180         free(fields[ i ]);
00181     }
00182     free(fields);
00183 }
00184 
00185 
00186 
00187 
00198 void create_bibtex_entry
00199 (
00200     Bibtex_entry** entry_out, 
00201     const char*    type, 
00202     const char*    key
00203 )
00204 {
00205     Bibtex_entry* entry;
00206 
00207     if (*entry_out == NULL)
00208     {
00209         assert(*entry_out = malloc(sizeof(Bibtex_entry)));
00210         (*entry_out)->type = NULL;
00211         (*entry_out)->key = NULL;
00212         (*entry_out)->fields = NULL;
00213         (*entry_out)->num_fields = 0;
00214         (*entry_out)->num_unused_fields = 0;
00215     }
00216     else
00217     {
00218         (*entry_out)->num_unused_fields += (*entry_out)->num_fields;
00219         (*entry_out)->num_fields = 0;
00220     }
00221     entry = *entry_out;
00222 
00223     entry->type = malloc(sizeof(char)*strlen(type));
00224     entry->key = malloc(sizeof(char)*strlen(key));
00225 
00226     strcpy(entry->type, type);
00227     strcpy(entry->key, key);
00228 }
00229 
00230 
00232 void free_bibtex_entry(Bibtex_entry* entry)
00233 {
00234     if (entry == NULL)
00235         return;
00236 
00237     free_bibtex_fields(entry->fields, entry->num_fields + 
00238             entry->num_unused_fields);
00239     free(entry->type);
00240     free(entry->key);
00241     free(entry);
00242 }
00243 
00244 
00250 void add_field_to_bibtex_entry
00251 (
00252     Bibtex_entry* entry,
00253     const char*   name,
00254     const char*   value
00255 )
00256 {
00257     Bibtex_field* field = NULL;
00258 
00259     if (entry->num_unused_fields > 0)
00260     {
00261         entry->num_unused_fields--;
00262         entry->num_fields++;;
00263         field = entry->fields[ entry->num_fields-1 ];
00264     }
00265     else
00266     {
00267         entry->num_fields++;
00268         assert(entry->fields = realloc(entry->fields, 
00269                 entry->num_fields*sizeof(Bibtex_field*)));
00270     }
00271 
00272     create_bibtex_field(&field, name, value);
00273     entry->fields[ entry->num_fields-1 ] = field;
00274 }
00275 
00276 
00281 void write_bibtex_entry(Bibtex_entry* entry, FILE* fp)
00282 {
00283     uint32_t i;
00284 
00285     fprintf(fp, "@%s{%s", entry->type, entry->key);
00286 
00287     for (i = 0; i < entry->num_fields; i++)
00288     {
00289         fprintf(fp, ",\n    %*s = {%s}", 10, 
00290                 entry->fields[ i ]->name, entry->fields[ i ]->value);
00291     }
00292 
00293     fprintf(fp, "\n}\n");
00294 }