1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim 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 GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
26 #include "core/GP_Debug.h"
28 #include "GP_MetaData.h"
31 struct GP_MetaRecord
*root
;
32 struct GP_MetaRecord
*last
;
33 unsigned int rec_count
;
39 static unsigned int do_hash(const char *id
)
41 unsigned int hash
= 0;
52 GP_MetaData
*GP_MetaDataCreate(unsigned int expected_records
)
55 size_t size
= expected_records
* sizeof(struct GP_MetaRecord
);
57 GP_DEBUG(1, "Creating MetaData for %u records", expected_records
);
59 data
= malloc(sizeof(struct GP_MetaData
) + size
);
62 GP_DEBUG(1, "Malloc failed :(");
75 void GP_MetaDataClear(GP_MetaData
*self
)
77 GP_DEBUG(1, "Clearing MetaData %p with %u records",
78 self
, self
->rec_count
);
83 self
->free
= self
->size
;
86 void GP_MetaDataDestroy(GP_MetaData
*self
)
88 GP_DEBUG(1, "Destroying MetaData %p", self
);
92 void GP_MetaDataPrint(GP_MetaData
*self
)
96 printf("MetaData %u record(s)\n", self
->rec_count
);
98 for (rec
= self
->root
; rec
!= NULL
; rec
= rec
->next
) {
99 printf("%-32s: ", rec
->id
);
103 printf("%i\n", rec
->val
.i
);
105 case GP_META_RATIONAL
:
106 printf("%i/%i\n", rec
->val
.r
.num
, rec
->val
.r
.den
);
109 printf("'%s'\n", rec
->val
.str
);
112 printf("%lf\n", rec
->val
.d
);
118 static GP_MetaRecord
*record_lookup(GP_MetaData
*self
, const char *id
,
123 for (rec
= self
->root
; rec
!= NULL
; rec
= rec
->next
)
124 if (rec
->hash
== hash
&& !strcmp(rec
->id
, id
))
130 static void *do_alloc(struct GP_MetaData
*self
, size_t size
)
132 if (self
->free
< size
) {
133 GP_DEBUG(0, "TODO: storage full");
137 void *ret
= ((char*)self
) + sizeof(struct GP_MetaData
) + (self
->size
- self
->free
);
144 static GP_MetaRecord
*record_create(GP_MetaData
*self
, const char *id
,
149 if (strlen(id
) + 1 > GP_META_RECORD_ID_MAX
) {
150 GP_DEBUG(0, "Can't create id '%s' longer than %i chars",
151 id
, GP_META_RECORD_ID_MAX
- 1);
155 rec
= do_alloc(self
, sizeof(struct GP_MetaRecord
));
163 if (self
->root
== NULL
) {
167 self
->last
->next
= rec
;
177 GP_MetaRecord
*GP_MetaDataCreateRecord(GP_MetaData
*self
, const char *id
)
179 unsigned int hash
= do_hash(id
);
181 if (record_lookup(self
, id
, hash
)) {
182 GP_DEBUG(1, "Trying to create duplicate record id '%s'", id
);
186 return record_create(self
, id
, hash
);
189 int GP_MetaDataGetInt(GP_MetaData
*self
, const char *id
, int *res
)
193 GP_DEBUG(2, "Looking for GP_META_INT id '%s'", id
);
195 rec
= record_lookup(self
, id
, do_hash(id
));
198 GP_DEBUG(3, "Record id '%s' not found", id
);
202 if (rec
->type
!= GP_META_INT
) {
203 GP_DEBUG(3, "Record id '%s' has wrong type", id
);
209 GP_DEBUG(3, "Found GP_META_INT id '%s' = %i", id
, *res
);
214 int GP_MetaDataGetDouble(GP_MetaData
*self
, const char *id
, double *res
)
218 GP_DEBUG(2, "Looking for GP_META_DOUBLE id '%s'", id
);
220 rec
= record_lookup(self
, id
, do_hash(id
));
223 GP_DEBUG(3, "Record id '%s' not found", id
);
227 if (rec
->type
!= GP_META_DOUBLE
) {
228 GP_DEBUG(3, "Record id '%s' has wrong type", id
);
234 GP_DEBUG(3, "Found GP_META_DOUBLE id '%s' = %lf", id
, *res
);
239 const char *GP_MetaDataGetString(GP_MetaData
*self
, const char *id
)
243 GP_DEBUG(2, "Looking for GP_META_STRING id '%s'", id
);
245 rec
= record_lookup(self
, id
, do_hash(id
));
248 GP_DEBUG(3, "Record id '%s' not found", id
);
252 if (rec
->type
!= GP_META_STRING
) {
253 GP_DEBUG(3, "Record id '%s' has wrong type", id
);
257 GP_DEBUG(3, "Found GP_META_STRING id '%s' = '%s'", id
, rec
->val
.str
);
262 GP_MetaRecord
*GP_MetaDataCreateInt(GP_MetaData
*self
, const char *id
, int val
)
266 GP_DEBUG(2, "Creating GP_META_INT id '%s' = %i", id
, val
);
268 rec
= GP_MetaDataCreateRecord(self
, id
);
273 rec
->type
= GP_META_INT
;
279 GP_MetaRecord
*GP_MetaDataCreateRat(GP_MetaData
*self
, const char *id
,
284 GP_DEBUG(2, "Creating GP_META_RATIONAL id '%s' = %i/%i", id
, num
, den
);
287 GP_DEBUG(1, "Would not create '%s' with denominator == 0", id
);
291 rec
= GP_MetaDataCreateRecord(self
, id
);
296 rec
->type
= GP_META_RATIONAL
;
297 rec
->val
.r
.num
= num
;
298 rec
->val
.r
.den
= den
;
303 GP_MetaRecord
*GP_MetaDataCreateDouble(GP_MetaData
*self
, const char *id
,
308 GP_DEBUG(2, "Creating GP_META_DOUBLE id '%s' = %lf", id
, val
);
310 rec
= GP_MetaDataCreateRecord(self
, id
);
315 rec
->type
= GP_META_DOUBLE
;
321 GP_MetaRecord
*GP_MetaDataCreateString(GP_MetaData
*self
, const char *id
,
322 const char *str
, int len
, int dup
)
326 GP_DEBUG(2, "Creating GP_META_STRING id '%s' = '%s'", id
, str
);
328 rec
= GP_MetaDataCreateRecord(self
, id
);
338 size
= strlen(str
) + 1;
342 /* Play safe with aligment */
344 size
+= 8 - size
% 8;
346 //TODO: allocation error
347 s
= do_alloc(self
, size
);
348 strncpy(s
, str
, size
- 1);
353 rec
->type
= GP_META_STRING
;