File: refstr.c

package info (click to toggle)
graphviz 1.7.16-2
  • links: PTS
  • area: non-free
  • in suites: woody
  • size: 11,124 kB
  • ctags: 12,650
  • sloc: ansic: 131,002; sh: 7,483; makefile: 1,954; tcl: 1,760; yacc: 1,758; perl: 253; awk: 150; lex: 96
file content (143 lines) | stat: -rw-r--r-- 2,715 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
    This software may only be used by you under license from AT&T Corp.
    ("AT&T").  A copy of AT&T's Source Code Agreement is available at
    AT&T's Internet website having the URL:
    <http://www.research.att.com/sw/tools/graphviz/license/source.html>
    If you received this software without first entering into a license
    with AT&T, you have an infringing copy of this software and cannot use
    it without violating AT&T's intellectual property rights.
*/

#pragma prototyped
#include <aghdr.h>

#ifdef DMALLOC
#include "dmalloc.h"
#endif

/*
 * reference counted strings.
 */

typedef struct refstr_t {
	Dtlink_t		link;
	unsigned long	refcnt;
	char			*s;
	char			store[1];		/* this is actually a dynamic array */
} refstr_t;

static Dtdisc_t Refstrdisc = {
	offsetof(refstr_t,s),	/* key */
	-1,						/* size */
	0,						/* link offset */
	NIL(Dtmake_f),
	agdictobjfree,
	NIL(Dtcompar_f),
	NIL(Dthash_f),
	agdictobjmem,
	NIL(Dtevent_f)
};

static Dict_t *Refdict_default;

static Dict_t *refdict(Agraph_t *g)
{
	Dict_t	**dictref;

	if (g) dictref = &(g->clos->strdict);
	else dictref = &Refdict_default;
	if (*dictref == NIL(Dict_t*))
		*dictref = agdtopen(g,&Refstrdisc,Dttree);
	return *dictref;
}

void agstrclose(Agraph_t *g)
{
	agdtclose(g,refdict(g));
}

static refstr_t *refsymbind(Dict_t *strdict, char *s)
{
	refstr_t		key,*r;
	key.s = s;
	r = (refstr_t*) dtsearch(strdict,&key);
	return r;
}

static char *refstrbind(Dict_t *strdict, char *s)
{
	refstr_t	*r;
	r = refsymbind(strdict, s);
	if (r) return r->s;
	else return NIL(char*);
}

char *agstrbind(Agraph_t *g, char *s)
{
	return refstrbind(refdict(g),s);
}

char *agstrdup(Agraph_t *g, char *s)
{
	refstr_t		*r;
	Dict_t			*strdict;
	size_t			sz;

	if (s == NIL(char*)) return NIL(char*);
	strdict = refdict(g);
	r = refsymbind(strdict,s);
	if (r) r->refcnt++;
	else {
		sz = sizeof(refstr_t)+strlen(s);
		if (g) r = (refstr_t*) agalloc(g,sz);
		else r = (refstr_t*)malloc(sz);
		r->refcnt = 1;
		strcpy(r->store,s);
		r->s = r->store;
		dtinsert(strdict,r);
	}
	return r->s;
}

int agstrfree(Agraph_t *g, char *s)
{
	refstr_t		*r;
	Dict_t			*strdict;

	if (s == NIL(char*))
		return FAILURE;

	strdict = refdict(g);
	r = refsymbind(strdict,s);
	if (r && (r->s == s)) {
		r->refcnt--;
		if (r->refcnt <= 0) {
			agdtdelete(g,strdict,r);
			/*
			if (g) agfree(g,r);
			else free(r);
			*/
		}
	}
	if (r == NIL(refstr_t*)) return FAILURE;
	return SUCCESS;
}

#ifdef DEBUG
static int refstrprint(Dict_t *dict, void *ptr, void *user)
{
	refstr_t *r;

	NOTUSED(dict);
	r = ptr;
	NOTUSED(user);
	write(2,r->s,strlen(r->s));
	write(2,"\n",1);
	return 0;
}

void agrefstrdump(Agraph_t *g)
{
	dtwalk(Refdict_default,refstrprint,0);
}
#endif