1 /* a managed FILE* ... for lazy file read
2 */
3
4 /*
5
6 Copyright (C) 1991-2003 The National Gallery
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
22 */
23
24 /*
25
26 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
27
28 */
29
30 #include "ip.h"
31
32 /*
33 #define DEBUG
34 */
35
36 static ManagedClass *parent_class = NULL;
37
38 /* Track all instances here.
39 */
40 static GHashTable *managedstring_all = NULL;
41
42 #ifdef DEBUG
43 /* Number of managed strings, number we have expanded to the heap.
44 */
45 int managed_total = 0;
46 int managed_expanded = 0;
47 #endif /*DEBUG*/
48
49 static void
managedstring_finalize(GObject * gobject)50 managedstring_finalize( GObject *gobject )
51 {
52 Managedstring *managedstring = MANAGEDSTRING( gobject );
53
54 #ifdef DEBUG
55 printf( "managedstring_finalize: \"%s\", ", managedstring->string );
56 iobject_print( IOBJECT( managedstring ) );
57 #endif /*DEBUG*/
58
59 #ifdef DEBUG
60 {
61 PElement pe;
62
63 PEPOINTE( &pe, &managedstring->e );
64 if( !PEISNOVAL( &pe ) )
65 managed_expanded -= 1;
66 managed_total -= 1;
67 }
68 #endif /*DEBUG*/
69
70 heap_unregister_element( MANAGED( managedstring )->heap,
71 &managedstring->e );
72 g_hash_table_remove( managedstring_all, managedstring );
73 IM_FREE( managedstring->string );
74
75 G_OBJECT_CLASS( parent_class )->finalize( gobject );
76 }
77
78 static void
managedstring_info(iObject * iobject,VipsBuf * buf)79 managedstring_info( iObject *iobject, VipsBuf *buf )
80 {
81 Managedstring *managedstring = MANAGEDSTRING( iobject );
82
83 vips_buf_appendf( buf, "managedstring->string = \"%s\"\n",
84 managedstring->string );
85
86 IOBJECT_CLASS( parent_class )->info( iobject, buf );
87 }
88
89 /* Hash and equality for a managed string: we need the string and the heap to
90 * match.
91 */
92 static unsigned int
managedstring_hash(Managedstring * managedstring)93 managedstring_hash( Managedstring *managedstring )
94 {
95 return( g_str_hash( managedstring->string ) |
96 GPOINTER_TO_UINT( ((Managed *) managedstring)->heap ) );
97 }
98
99 static gboolean
managedstring_equal(Managedstring * a,Managedstring * b)100 managedstring_equal( Managedstring *a, Managedstring *b )
101 {
102 return( ((Managed *) a)->heap == ((Managed *) b)->heap &&
103 g_str_equal( a->string, b->string ) );
104 }
105
106 static void
managedstring_all_init(void)107 managedstring_all_init( void )
108 {
109 if( !managedstring_all )
110 managedstring_all = g_hash_table_new(
111 (GHashFunc) managedstring_hash,
112 (GEqualFunc) managedstring_equal );
113 }
114
115 static void
managedstring_class_init(ManagedstringClass * class)116 managedstring_class_init( ManagedstringClass *class )
117 {
118 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
119 iObjectClass *iobject_class = IOBJECT_CLASS( class );
120
121 parent_class = g_type_class_peek_parent( class );
122
123 gobject_class->finalize = managedstring_finalize;
124
125 iobject_class->info = managedstring_info;
126
127 managedstring_all_init();
128 }
129
130 static void
managedstring_init(Managedstring * managedstring)131 managedstring_init( Managedstring *managedstring )
132 {
133 #ifdef DEBUG
134 printf( "managedstring_init: %p\n", managedstring );
135 #endif /*DEBUG*/
136
137 #ifdef DEBUG
138 managed_total += 1;
139 #endif /*DEBUG*/
140
141 managedstring->string = NULL;
142 managedstring->e.type = ELEMENT_NOVAL;
143 managedstring->e.ele = NULL;
144 }
145
146 GType
managedstring_get_type(void)147 managedstring_get_type( void )
148 {
149 static GType type = 0;
150
151 if( !type ) {
152 static const GTypeInfo info = {
153 sizeof( ManagedstringClass ),
154 NULL, /* base_init */
155 NULL, /* base_finalize */
156 (GClassInitFunc) managedstring_class_init,
157 NULL, /* class_finalize */
158 NULL, /* class_data */
159 sizeof( Managedstring ),
160 32, /* n_preallocs */
161 (GInstanceInitFunc) managedstring_init,
162 };
163 type = g_type_register_static( TYPE_MANAGED,
164 "Managedstring", &info, 0 );
165 }
166
167 return( type );
168 }
169
170 static Managedstring *
managedstring_new(Heap * heap,const char * string)171 managedstring_new( Heap *heap, const char *string )
172 {
173 Managedstring *managedstring;
174
175 #ifdef DEBUG
176 printf( "managedstring_new: %p, %s\n", heap, string );
177 #endif /*DEBUG*/
178
179 /* Disallow "" as string, we want to represent that as [].
180 */
181 g_assert( strcmp( string, "" ) != 0 );
182
183 managedstring = g_object_new( TYPE_MANAGEDSTRING, NULL );
184 managed_link_heap( MANAGED( managedstring ), heap );
185 heap_register_element( heap, &managedstring->e );
186 if( !(managedstring->string = im_strdup( NULL, string )) )
187 return( NULL );
188
189 g_assert( !g_hash_table_lookup( managedstring_all, managedstring ) );
190 g_hash_table_insert( managedstring_all, managedstring, managedstring );
191
192 MANAGED( managedstring )->hash = managedstring_hash( managedstring );
193
194 return( managedstring );
195 }
196
197 Managedstring *
managedstring_lookup(Heap * heap,const char * string)198 managedstring_lookup( Heap *heap, const char *string )
199 {
200 Managedstring managedstring;
201
202 ((Managed *) &managedstring)->heap = heap;
203 managedstring.string = string;
204 managedstring_all_init();
205
206 return( g_hash_table_lookup( managedstring_all, &managedstring ) );
207 }
208
209 Managedstring *
managedstring_find(Heap * heap,const char * string)210 managedstring_find( Heap *heap, const char *string )
211 {
212 Managedstring *managedstring;
213
214 if( !(managedstring = managedstring_lookup( heap, string )) )
215 if( !(managedstring = managedstring_new( heap, string )) )
216 return( NULL );
217
218 return( managedstring );
219 }
220
221 gboolean
managedstring_get(Managedstring * managedstring,PElement * out)222 managedstring_get( Managedstring *managedstring, PElement *out )
223 {
224 PElement pe;
225
226 PEPOINTE( &pe, &managedstring->e );
227 if( PEISNOVAL( &pe ) ) {
228 if( !heap_string_new( MANAGED( managedstring )->heap,
229 managedstring->string, &pe ) )
230 return( FALSE );
231
232 #ifdef DEBUG
233 managed_expanded += 1;
234 printf( "expanding %s to the heap\n", managedstring->string );
235 printf( "\t(%d of %d now expanded)\n",
236 managed_expanded, managed_total );
237 #endif /*DEBUG*/
238 }
239
240 PEPUTE( out, &managedstring->e );
241
242 return( TRUE );
243 }
244