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 (%.4f)\n", rec
->val
.r
.num
, rec
->val
.r
.den
,
107 (float)rec
->val
.r
.num
/ rec
->val
.r
.den
);
110 printf("'%s'\n", rec
->val
.str
);
113 printf("%lf\n", rec
->val
.d
);
119 static GP_MetaRecord
*record_lookup(GP_MetaData
*self
, const char *id
,
124 for (rec
= self
->root
; rec
!= NULL
; rec
= rec
->next
)
125 if (rec
->hash
== hash
&& !strcmp(rec
->id
, id
))
131 static void *do_alloc(struct GP_MetaData
*self
, size_t size
)
133 if (self
->free
< size
) {
134 GP_DEBUG(0, "TODO: storage full");
138 void *ret
= ((char*)self
) + sizeof(struct GP_MetaData
) + (self
->size
- self
->free
);
145 static GP_MetaRecord
*record_create(GP_MetaData
*self
, const char *id
,
150 if (strlen(id
) + 1 > GP_META_RECORD_ID_MAX
) {
151 GP_DEBUG(0, "Can't create id '%s' longer than %i chars",
152 id
, GP_META_RECORD_ID_MAX
- 1);
156 rec
= do_alloc(self
, sizeof(struct GP_MetaRecord
));
165 if (self
->root
== NULL
) {
169 self
->last
->next
= rec
;
178 GP_MetaRecord
*GP_MetaDataCreateRecord(GP_MetaData
*self
, const char *id
)
180 unsigned int hash
= do_hash(id
);
182 if (record_lookup(self
, id
, hash
)) {
183 GP_DEBUG(1, "Trying to create duplicate record id '%s'", id
);
187 return record_create(self
, id
, hash
);
190 int GP_MetaDataGetInt(GP_MetaData
*self
, const char *id
, int *res
)
194 GP_DEBUG(2, "Looking for GP_META_INT id '%s'", id
);
196 rec
= record_lookup(self
, id
, do_hash(id
));
199 GP_DEBUG(3, "Record id '%s' not found", id
);
203 if (rec
->type
!= GP_META_INT
) {
204 GP_DEBUG(3, "Record id '%s' has wrong type", id
);
210 GP_DEBUG(3, "Found GP_META_INT id '%s' = %i", id
, *res
);
215 int GP_MetaDataGetDouble(GP_MetaData
*self
, const char *id
, double *res
)
219 GP_DEBUG(2, "Looking for GP_META_DOUBLE id '%s'", id
);
221 rec
= record_lookup(self
, id
, do_hash(id
));
224 GP_DEBUG(3, "Record id '%s' not found", id
);
228 if (rec
->type
!= GP_META_DOUBLE
) {
229 GP_DEBUG(3, "Record id '%s' has wrong type", id
);
235 GP_DEBUG(3, "Found GP_META_DOUBLE id '%s' = %lf", id
, *res
);
240 const char *GP_MetaDataGetString(GP_MetaData
*self
, const char *id
)
244 GP_DEBUG(2, "Looking for GP_META_STRING id '%s'", id
);
246 rec
= record_lookup(self
, id
, do_hash(id
));
249 GP_DEBUG(3, "Record id '%s' not found", id
);
253 if (rec
->type
!= GP_META_STRING
) {
254 GP_DEBUG(3, "Record id '%s' has wrong type", id
);
258 GP_DEBUG(3, "Found GP_META_STRING id '%s' = '%s'", id
, rec
->val
.str
);
263 GP_MetaRecord
*GP_MetaDataCreateInt(GP_MetaData
*self
, const char *id
, int val
)
267 GP_DEBUG(2, "Creating GP_META_INT id '%s' = %i", id
, val
);
269 rec
= GP_MetaDataCreateRecord(self
, id
);
274 rec
->type
= GP_META_INT
;
280 GP_MetaRecord
*GP_MetaDataCreateRat(GP_MetaData
*self
, const char *id
,
285 GP_DEBUG(2, "Creating GP_META_RATIONAL id '%s' = %i/%i", id
, num
, den
);
288 GP_DEBUG(1, "Would not create '%s' with denominator == 0", id
);
292 rec
= GP_MetaDataCreateRecord(self
, id
);
297 rec
->type
= GP_META_RATIONAL
;
298 rec
->val
.r
.num
= num
;
299 rec
->val
.r
.den
= den
;
304 GP_MetaRecord
*GP_MetaDataCreateDouble(GP_MetaData
*self
, const char *id
,
309 GP_DEBUG(2, "Creating GP_META_DOUBLE id '%s' = %lf", id
, val
);
311 rec
= GP_MetaDataCreateRecord(self
, id
);
316 rec
->type
= GP_META_DOUBLE
;
322 GP_MetaRecord
*GP_MetaDataCreateString(GP_MetaData
*self
, const char *id
,
323 const char *str
, int len
, int dup
)
327 GP_DEBUG(2, "Creating GP_META_STRING id '%s' = '%s'", id
, str
);
329 rec
= GP_MetaDataCreateRecord(self
, id
);
343 /* Play safe with aligment */
345 size
+= 8 - size
% 8;
347 //TODO: allocation error
348 s
= do_alloc(self
, size
);
354 rec
->type
= GP_META_STRING
;