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