Graphviz  2.29.20120524.0446
lib/graph/refstr.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 
00015 #include        "libgraph.h"
00016 #include        <assert.h>
00017 
00018 static unsigned int HTML_BIT;
00019 static unsigned int CNT_BITS;
00020 
00021 #ifdef DMALLOC
00022 #include "dmalloc.h"
00023 #endif
00024 
00025 typedef struct refstr_t {
00026     Dtlink_t link;
00027     unsigned int refcnt;
00028     char s[1];
00029 } refstr_t;
00030 
00031 static Dtdisc_t Refstrdisc = {
00032     offsetof(refstr_t, s[0]),
00033     0,
00034     0,
00035     ((Dtmake_f) 0),
00036     ((Dtfree_f) 0),
00037     ((Dtcompar_f) 0),           /* use strcmp */
00038     ((Dthash_f) 0),
00039     ((Dtmemory_f) 0),
00040     ((Dtevent_f) 0)
00041 };
00042 
00043 static Dict_t *StringDict;
00044 
00045 #ifdef DEBUG
00046 static int refstrprint(Dt_t * d, Void_t * obj, Void_t * env)
00047 {
00048     refstr_t *r = (refstr_t *) obj;
00049     fprintf(stderr, "%s\n", r->s);
00050     return 0;
00051 }
00052 
00053 void agrefstrdump(void)
00054 {
00055     dtwalk(StringDict, refstrprint, 0);
00056 }
00057 #endif
00058 
00059 /* initialize_strings:
00060  * Create dictionary and masks for HTML strings.
00061  * HTML_BIT must be the most significant bit. We assume 8-bit bytes.
00062  */
00063 static void initialize_strings(void)
00064 {
00065     StringDict = dtopen(&Refstrdisc, Dttree);
00066     HTML_BIT = ((unsigned int) 1) << (sizeof(unsigned int) * 8 - 1);
00067     CNT_BITS = ~HTML_BIT;
00068 }
00069 
00070 char *agstrdup(char *s)
00071 {
00072     refstr_t *key, *r;
00073 
00074     if (StringDict == NULL)
00075         initialize_strings();
00076     if (s == NULL)
00077         return s;
00078 
00079     key = (refstr_t *) (s - offsetof(refstr_t, s[0]));
00080     r = (refstr_t *) dtsearch(StringDict, key);
00081     if (r)
00082         r->refcnt++;
00083     else {
00084         r = (refstr_t *) malloc(sizeof(refstr_t) + strlen(s));
00085         r->refcnt = 1;
00086         strcpy(r->s, s);
00087         dtinsert(StringDict, r);
00088     }
00089     return r->s;
00090 }
00091 
00092 /* agstrdup_html:
00093  * For various purposes, including deparsing, we have to recognize
00094  * strings coming from <...> rather than "...". To do this, we set
00095  * the top bit of the refcnt field. Since the use of html strings
00096  * is localized, we allow the application to make the distinction.
00097  */
00098 char *agstrdup_html(char *s)
00099 {
00100     refstr_t *key, *r;
00101 
00102     if (StringDict == NULL)
00103         initialize_strings();
00104     if (s == NULL)
00105         return s;
00106 
00107     key = (refstr_t *) (s - offsetof(refstr_t, s[0]));
00108     r = (refstr_t *) dtsearch(StringDict, key);
00109     if (r)
00110         r->refcnt++;
00111     else {
00112         r = (refstr_t *) malloc(sizeof(refstr_t) + strlen(s));
00113         r->refcnt = 1 | HTML_BIT;
00114         strcpy(r->s, s);
00115         dtinsert(StringDict, r);
00116     }
00117     return r->s;
00118 }
00119 
00120 void agstrfree(char *s)
00121 {
00122     refstr_t *key, *r;
00123 
00124     if ((StringDict == NULL) || (s == NULL))
00125         return;
00126     key = (refstr_t *) (s - offsetof(refstr_t, s[0]));
00127     r = (refstr_t *) dtsearch(StringDict, key);
00128 
00129     if (r) {
00130         r->refcnt--;
00131         if ((r->refcnt && CNT_BITS) == 0) {
00132             dtdelete(StringDict, r);
00133             free(r);
00134         }
00135     } else
00136         agerr(AGERR, "agstrfree lost %s\n", s);
00137 }
00138 
00139 /* aghtmlstr:
00140  * Return true if s is an HTML string.
00141  * We assume s points to the datafield s[0] of a refstr.
00142  */
00143 int aghtmlstr(char *s)
00144 {
00145     refstr_t *key;
00146 
00147     if ((StringDict == NULL) || (s == NULL))
00148         return 0;
00149     key = (refstr_t *) (s - offsetof(refstr_t, s[0]));
00150     return (key->refcnt & HTML_BIT);
00151 }