00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "libgraph.h"
00019 #include <assert.h>
00020
00021 static unsigned int HTML_BIT;
00022 static unsigned int CNT_BITS;
00023
00024 #ifdef DMALLOC
00025 #include "dmalloc.h"
00026 #endif
00027
00028 typedef struct refstr_t {
00029 Dtlink_t link;
00030 unsigned int refcnt;
00031 char s[1];
00032 } refstr_t;
00033
00034 static Dtdisc_t Refstrdisc = {
00035 offsetof(refstr_t, s[0]),
00036 0,
00037 0,
00038 ((Dtmake_f) 0),
00039 ((Dtfree_f) 0),
00040 ((Dtcompar_f) 0),
00041 ((Dthash_f) 0),
00042 ((Dtmemory_f) 0),
00043 ((Dtevent_f) 0)
00044 };
00045
00046 static Dict_t *StringDict;
00047
00048 #ifdef DEBUG
00049 static int refstrprint(Dt_t * d, Void_t * obj, Void_t * env)
00050 {
00051 refstr_t *r = (refstr_t *) obj;
00052 fprintf(stderr, "%s\n", r->s);
00053 return 0;
00054 }
00055
00056 void agrefstrdump(void)
00057 {
00058 dtwalk(StringDict, refstrprint, 0);
00059 }
00060 #endif
00061
00062
00063
00064
00065
00066 static void initialize_strings(void)
00067 {
00068 StringDict = dtopen(&Refstrdisc, Dttree);
00069 HTML_BIT = ((unsigned int) 1) << (sizeof(unsigned int) * 8 - 1);
00070 CNT_BITS = ~HTML_BIT;
00071 }
00072
00073 char *agstrdup(char *s)
00074 {
00075 refstr_t *key, *r;
00076
00077 if (StringDict == NULL)
00078 initialize_strings();
00079 if (s == NULL)
00080 return s;
00081
00082 key = (refstr_t *) (s - offsetof(refstr_t, s[0]));
00083 r = (refstr_t *) dtsearch(StringDict, key);
00084 if (r)
00085 r->refcnt++;
00086 else {
00087 r = (refstr_t *) malloc(sizeof(refstr_t) + strlen(s));
00088 r->refcnt = 1;
00089 strcpy(r->s, s);
00090 dtinsert(StringDict, r);
00091 }
00092 return r->s;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101 char *agstrdup_html(char *s)
00102 {
00103 refstr_t *key, *r;
00104
00105 if (StringDict == NULL)
00106 initialize_strings();
00107 if (s == NULL)
00108 return s;
00109
00110 key = (refstr_t *) (s - offsetof(refstr_t, s[0]));
00111 r = (refstr_t *) dtsearch(StringDict, key);
00112 if (r)
00113 r->refcnt++;
00114 else {
00115 r = (refstr_t *) malloc(sizeof(refstr_t) + strlen(s));
00116 r->refcnt = 1 | HTML_BIT;
00117 strcpy(r->s, s);
00118 dtinsert(StringDict, r);
00119 }
00120 return r->s;
00121 }
00122
00123 void agstrfree(char *s)
00124 {
00125 refstr_t *key, *r;
00126
00127 if ((StringDict == NULL) || (s == NULL))
00128 return;
00129 key = (refstr_t *) (s - offsetof(refstr_t, s[0]));
00130 r = (refstr_t *) dtsearch(StringDict, key);
00131
00132 if (r) {
00133 r->refcnt--;
00134 if ((r->refcnt && CNT_BITS) == 0) {
00135 dtdelete(StringDict, r);
00136 free(r);
00137 }
00138 } else
00139 agerr(AGERR, "agstrfree lost %s\n", s);
00140 }
00141
00142
00143
00144
00145
00146 int aghtmlstr(char *s)
00147 {
00148 refstr_t *key;
00149
00150 if ((StringDict == NULL) || (s == NULL))
00151 return 0;
00152 key = (refstr_t *) (s - offsetof(refstr_t, s[0]));
00153 return (key->refcnt & HTML_BIT);
00154 }