1 /*
2  * Copyright (C) 1998,1999 Uwe Ohse
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * As a special exception this source may be used as part of the
19  * SRS project by CORE/Computer Service Langenbach
20  * regardless of the copyright they choose.
21  *
22  * Contact: uwe@ohse.de
23  */
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <unistd.h> /* write */
27 #include "uostr.h"
28 
29 /* core functions */
30 
31 	/* assume max. overhead of malloc() */
32 #define OVERHEAD (sizeof(void *)+sizeof(size_t))
33 
34 #define DEBUG_FREE
35 
36 #ifdef DEBUG_FREE
37 int uostr_debug_free=1;
38 struct deb {
39 	uostr_t *adr;
40 	struct deb *next;
41 };
42 static struct deb *anker;
43 #endif
44 
45 void (*uostr_xallocfn) P__((const char *))=0;
46 void
uostr_xallocerr(const char * fn)47 uostr_xallocerr(const char *fn)
48 {
49 	if (uostr_xallocfn) uostr_xallocfn(fn);
50 	else {
51 		const char *p=fn; while(*p!=0) p++;
52 		write(2,"out of memory in ",17);
53 		write(2,fn,p-fn);
54 		write(2,"\n",1);
55 	}
56 	exit(1);
57 }
58 
59 uostr_t *
uostr_allocmore(uostr_t * u,size_t bytes)60 uostr_allocmore(uostr_t *u, size_t bytes)
61 {
62 	size_t n;
63 	size_t t;
64 	if (!u->data) n=bytes;
65 	else n=bytes+u->size;
66 	for (t=32;;t*=2) {
67 		if (t-OVERHEAD>=n)
68 			break;
69 	}
70 	t-=OVERHEAD;
71 	if (!u->data) {
72 		u->len=0;
73 #ifdef DEBUG_FREE
74 		if (uostr_debug_free) {
75 			struct deb *neu,*x;
76 			for (x=anker;x;x=x->next) { if (x->adr==u) break; }
77 			if (x) { write(2,"reusing uostr\n",14); abort(); }
78 			else {
79 				neu=(struct deb *) malloc(sizeof(struct deb));
80 				if (!neu) {
81 					uostr_debug_free=0;
82 					while (anker) { struct deb *next; next=anker->next; free(anker); anker=next; }
83 				} else { neu->adr=u; neu->next=anker; anker=neu; }
84 			}
85 		}
86 #endif
87 		u->data=(char *) malloc(t);
88 		if (!u->data) { errno=ENOMEM; return 0;}
89 	}
90 	else {
91 		char *tmp=(char *) realloc(u->data,t);
92 		if (!tmp) return 0;
93 		u->data=tmp;
94 	}
95 	u->size=t;
96 	return u;
97 }
98 uostr_t *
uostr_xallocmore(uostr_t * u,size_t bytes)99 uostr_xallocmore(uostr_t *u, size_t bytes)
100 { uostr_t *r=uostr_allocmore(u,bytes); if (r) return r; uostr_xallocerr("uostr_xallocmore"); return(0); }
101 
102 void
uostr_freedata(uostr_t * u)103 uostr_freedata(uostr_t *u)
104 {
105 	if (u->data) {
106 #ifdef DEBUG_FREE
107 		if (uostr_debug_free) {
108 			struct deb *x,*l;
109 			for (x=anker,l=0;x;) {
110 				if (x->adr==u) {
111 					struct deb *n=x->next;
112 					free(x);
113 					if (l) l->next=n;
114 					else anker=n;
115 					x=n;
116 					continue;
117 				}
118 				l=x;
119 				x=x->next;
120 			}
121 		}
122 #endif
123 		free(u->data);
124 		u->data=0;
125 	}
126 }
127 void
uostr_forget(uostr_t * u)128 uostr_forget(uostr_t *u)
129 {
130 #ifdef DEBUG_FREE
131 	if (uostr_debug_free) {
132 		struct deb *x,*l;
133 		for (x=anker,l=0;x;) {
134 			if (x->adr==u) {
135 				struct deb *n=x->next;
136 				free(x);
137 				if (l) l->next=n;
138 				else anker=n;
139 				x=n;
140 				continue;
141 			}
142 			l=x;
143 			x=x->next;
144 		}
145 	}
146 #endif
147 }
148